【问题标题】:pytest - command line argument outside test functionpytest - 测试函数外的命令行参数
【发布时间】:2020-08-04 13:26:42
【问题描述】:

如何将命令行选项作为变量传递给我的 pytest 非测试文件,例如数据库名称。

当我尝试时:

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

然后运行

 python -m pytest -e test1

看起来 pytest 无法获取 -e 标志

错误:用法:ma​​in.py [options] [file_or_dir] [file_or_dir] [...]

ma​​in.py:错误:无法识别的参数:-e

inifile:无

我也尝试 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

编辑 1

所以我的 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()

当我尝试运行时

py.test --db test1

我收到了这个错误

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

但是当我跑步时

py.test

我明白了

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

参数是必需的,但当我通过时它无法识别。如何处理?

【问题讨论】:

    标签: python python-3.x pytest


    【解决方案1】:

    欢迎!

    特别是要“覆盖”变量、模块和对象,您应该模拟它们。测试中的模拟是指在创建真实对象的成本很高时,创建一个与原始对象具有相似行为的假对象。比如数据库连接。但是,自然而然,它不仅限于数据库。您可以模拟任何对象,以及 sys.argv
    您可以在 pytest docs 中阅读更多关于模拟的信息,但这里有一个简短的示例

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

    话虽如此,我强烈建议您不要使用getopt。这是一种已弃用的解析来自bash 世界的参数的方法。有一个名为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

    编辑 1

    argparse 做得很好!

    现在,您可以简单地模拟它。您不再需要它解析命令行。您想控制它返回的内容。因此,这一次,当您使用monkeypatch 模拟argparse.ArgumentParser 时,您将传入您自己的“虚拟类”,当parser.parse_args() 被调用时,它只会返回固定参数。这是此类的一个示例(您可能需要对其进行调整)

    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)
    

    一个调整可能是让它更可重用,并添加你自己的构造函数,db 等于。

    【讨论】:

    • 在 EDIT 1 中,当我尝试运行它时出现错误:py.test: error: unrecognized arguments: --db
    • @Pat77 不确定您是否收到关于答案编辑的通知,但会添加更多内容。玩得开心!
    猜你喜欢
    • 1970-01-01
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-21
    相关资源
    最近更新 更多