【问题标题】:How do I activate a PyTest fixture from the command line?如何从命令行激活 PyTest 夹具?
【发布时间】:2020-11-25 18:34:45
【问题描述】:

我正在使用 Python3.8 和 pytest。如何根据某些命令行规范为我的会话激活夹具?现在我有一个 tests/conftest.py 文件,其中包含

@pytest.fixture(name="fixture1", scope="session")
def fixture1():
    ...

@pytest.fixture(name="fixture2", scope="session")
def fixture2():
    ...

但我只希望会话中包含某些固定装置,并且我希望能够在 pytest.ini 文件或通过传递给 pytest 的命令行参数中指定它。我该怎么做?

编辑:这是我的用例...

如果启用命令行选项,我想依赖一个夹具

@pytest.fixture(name="az_sql_db_inst")
def az_db_connection_fixture(az_sql_creds, wait_for_sql_server)

但是如果没有启用命令行,我想依赖另一个fixture ...

@pytest.fixture(name="az_sql_db_inst")
def az_db_connection_fixture(az_sql_creds, wait_for_docker_sql_server)

【问题讨论】:

    标签: python-3.x command-line pytest fixtures conftest


    【解决方案1】:

    您可以添加可用于启用灯具的命令行标志:

    conftest.py

    def pytest_addoption(parser):
        parser.addoption('--option2', action='store_const', const=True)
        parser.addoption('--option2', action='store_const', const=True)
    

    你必须在你的夹具中检查这些参数:

    @pytest.fixture(name="fixture1", scope="session", autouse=True)
    def fixture1(request):
       # only use with option1 command line argument
       if request.config.getoption("--option1"):
           ...
        
    @pytest.fixture(name="fixture2", scope="session", autouse=True)
    def fixture2(request):
       # only use with option2 command line argument
       if request.config.getoption("--option2"):
           ...
    
    @pytest.fixture(name="fixture3", scope="session", autouse=True)
    def fixture3(request):
       # only use if option1 command line argument is not provided
       if not request.config.getoption("--option1"):
           ...
    

    我在这里使用了autouse=True,因为我希望灯具执行不同的设置代码,当然您的使用可能会有所不同。

    你现在可以打电话了:

    • pytest -> 不会应用任何夹具
    • pytest --option1 -> 将应用fixture1
    • pytest --option1 --option2 -> 两个夹具都将被应用

    您也可以将这些参数添加到您的pytest.ini

    [pytest]
    # always apply fixture2
    addopts = --option2
    

    编辑:
    至于关于继承夹具的后续问题,您可以这样做:

    @pytest.fixture
    def wait_for_sql_server(request):
       if request.config.getoption("--my_option"):
           ...
    
    @pytest.fixture
    def wait_for_docker(request):
       if not request.config.getoption("--my_option"):
           ...
    
    @pytest.fixture(name="az_sql_db_inst")
    def az_db_connection_fixture(
        az_sql_creds, wait_for_sql_server, wait_for_docker):
        ...
    

    EDIT2:
    如果您无法自己编写或调整基本装置(问题的编辑部分中的wait_for_),您可以采用其他方式。

    您可以在单独的插件中编写基本夹具的单独实现,并根据配置加载所需的插件:

    plugin_docker.py

    @pytest.fixture
    def wait_for_service(wait_for_docker):
        yield
    

    plugin_server.py

    @pytest.fixture
    def wait_for_service(wait_for_sql_server):
        yield
    

    conftest.py

    def pytest_addoption(parser):
        parser.addoption('--docker', action='store_const', const=True)
    
    def pytest_configure(config):    
        use_docker = config.getoption("--docker")
        plugin_name = 'plugin_docker' if use_docker else 'plugin_server'
        if not config.pluginmanager.has_plugin(plugin_name):
            config.pluginmanager.import_plugin(plugin_name)
    
    @pytest.fixture(name="az_sql_db_inst")
    def az_db_connection_fixture(az_sql_creds, wait_for_service):
        ...    
    

    wait_for_service 固定装置只是实际固定装置的包装,但这样您就可以在两种情况下从同一个固定装置派生。

    【讨论】:

    • 非常感谢。我试图弄清楚如何重写我必须适应您在此处提供的内容,但我被卡住了(用示例编辑我的问题)。根据是否提供了命令行选项,我将如何使用命令行选项使我的夹具依赖于不同的夹具?
    • 我在答案中添加了这个,请检查是否可以使用。
    • 感谢您的扩展答案。这就是问题所在——我没有写其中一个固定装置(例如“wait_for_docker_sql_server”)。这是一个通过包含插件而包含在内的夹具。所以我实际上并不控制“wait_for_docker_sql_server”的方法体。不确定我是否仍然可以应用您上面的内容。
    • 在答案中添加了另一部分。
    猜你喜欢
    • 2015-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    相关资源
    最近更新 更多