简体   繁体   English

pytest - 测试外的命令行参数 function

[英]pytest - command line argument outside test function

How to pass command line option as variable to my pytest non test file eg database name.如何将命令行选项作为变量传递给我的 pytest 非测试文件,例如数据库名称。

When i try:当我尝试:

import sys
import getopt


"""argv = sys.argv[1:]

opts, args = getopt.getopt(argv, "e:")

for opt, arg in opts:
    if opt in ['-e']:
        if arg == "test1":
            base_url = "url-test1.com"
            db_name = "db_test1"
        elif arg == 'test2':
            base_url = "url-test2.com"
            db_name = "db_test2"
        elif arg == 'test3':
            base_url = "url-test3.com"
            db_name = "db_test3"
    return base_url

and run并运行

 python -m pytest -e test1

looks like pytest can't get -e flag看起来像 pytest 无法获得 -e 标志

ERROR: usage: main .py [options] [file_or_dir] [file_or_dir] [...]错误:用法: main .py [options] [file_or_dir] [file_or_dir] [...]

main .py: error: unrecognized arguments: -e.py:错误:无法识别的 arguments:-e

inifile: None inifile: 无

I also try pytest addoption and passing variable to test files works fine but how to pass cmnd line option as value to non test file?我也尝试 pytest addoption 并将变量传递给测试文件工作正常,但如何将 cmnd 行选项作为值传递给非测试文件?

def pytest_addoption(parser):
    parser.addoption("--url", action="store", default="url-test1.com")
    parser.addoption("--db", action="store", default="test1")

@pytest.fixture()
def url(request):
    return request.config.getoption("--url")

def db_name(request):
    return request.config.getoption("--db") #I want to pass this value to mysql.connector as database=db_name

EDIT 1编辑 1

so my db_connect.py lokks like that所以我的 db_connect.py 喜欢这样

import mysql.connector
import argparse


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--db', required=True, type=str, help="Your database name")
    return parser.parse_args()


def main():
    args = parse_args()
    db = args.db
    return db


mydb = mysql.connector.connect(
    user='username',
    password='password',
    host='host',
    database=main()
)


if __name__ == '__main__':
    main()

and when i try to run当我尝试跑步时

py.test --db test1

I got this error我收到了这个错误

ERROR: usage: py.test [options] [file_or_dir] [file_or_dir] [...]
py.test: error: unrecognized arguments: --db
  inifile: None

but when i run但是当我跑步时

py.test

i got我有

usage: py.test [-h] --db DB
py.test: error: the following arguments are required: --db

argument is required but when i pass it is unrecognized.参数是必需的,但是当我通过时,它无法识别。 How to handle it?如何处理?

Welcome!欢迎!

Specifically to "override" variables, modules and objects you should mock them.特别是要“覆盖”变量、模块和对象,您应该模拟它们。 Mocking in testing refers to creating a fake object with similar behavior to the original one when creating the real object is expensive.测试中的 Mocking 是指在创建真正的 object 时,创建与原始 object 具有相似行为的假 object 是昂贵的。 Such as database connections.比如数据库连接。 But, naturally, it isn't restricted to just databases.但是,当然,它不仅限于数据库。 You can mock any object, as well as sys.argv .您可以模拟任何 object 以及sys.argv
You can read more extensively about mocking in the pytest docs but here's a short example您可以在pytest文档中更广泛地阅读有关 mocking 的信息,但这是一个简短的示例

import module_to_test


def mytest(monkeypatch):
    """
    Mocks the configuration parameters values.
    """
    monkeypatch.setattr(module_to_test.sys, 'argv', ['somescript.py', '--db'])

That being said, I strongly recommend you do not use getopt .话虽如此,我强烈建议您不要使用getopt That is a deprecated method to parse arguments from the world of bash .这是从 bash 的世界中解析bash的不推荐使用的方法。 There is a strong package called argparse that entirely replaces any such argument boilerplate code.有一个强大的 package 称为argparse ,它完全取代了任何此类参数样板代码。

import argpase


def parse_args():
    """
    Parse arguments given in the command line. Expects just "--db"
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('--db', required=True, type=str, help="Your DB name")
    return parser.parse_args()


def main():
    args = parse_args()
    db = args.db
    print(f"Wrap 10 to {db}. Engage!")


if __name__ == '__main__':
    main()

argparse docs argparse 文档

edit 1编辑 1

Great work on that argparse !在那个argparse上做得很好!

Now, you can simply mock it.现在,您可以简单地模拟它。 You don't need it parsing the command line, anymore.您不再需要它解析命令行。 You want to control what it returns.您想控制它返回的内容。 So, this time, when you use monkeypatch to mock argparse.ArgumentParser , you'll pass in your own "dummy class" that does nothing but return fixed arguments when parser.parse_args() is called.因此,这一次,当您使用monkeypatch模拟argparse.ArgumentParser时,您将传入您自己的“虚拟类”,它什么都不做,只会在parser.parse_args()时返回固定的 arguments。 Here's an example of such a class (you'll probably want to tweak it)这是 class 的示例(您可能需要对其进行调整)

from collections import namedtuple


class DummyParser:
    def add_argument(self, *_, **__):
        """
        We know what arguments we want, we don't need to implement this.
        """
        pass

    def parse_args():
        """
        Money time!
        """
        fake_return_class = namedtuple('Namespace',
                                       ['db', 'the value we want for db'])
        args = fake_return_class(db="the value we want")
        return args


fake_parser = DummyParser()
fake_args = fake_parser.parse_args()
print(fake_args.db)

One tweak could be to make it a little more reusable and add your own constructor of what'll db be equal to.一项调整可能是使其更具可重用性,并添加您自己的db等于的构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM