在pytest跳过条件下使用命令行选项

时间:2018-08-16 18:48:12

标签: python pytest

长话短说,如果会话是针对我们的生产API运行的,我希望能够跳过一些测试。使用命令行选项设置要运行测试的环境。

我遇到了使用pytest_namespace来跟踪全局变量的想法,因此我在conftest.py文件中进行了设置。

def pytest_namespace():
    return {'global_env': ''}

我使用命令行选项,并在conftest.py的固定装置中设置各种API url(来自config.ini文件)。

@pytest.fixture(scope='session', autouse=True)
def configInfo(pytestconfig):
    global data
    environment = pytestconfig.getoption('--ENV')
    print(environment)
    environment = str.lower(environment)

    pytest.global_env = environment

    config = configparser.ConfigParser()
    config.read('config.ini') # local config file
    configData = config['QA-CONFIG']
    if environment == 'qa':
            configData = config['QA-CONFIG']
    if environment == 'prod':
            configData = config['PROD-CONFIG']

(...)

然后我有要跳过的测试,它的装饰像这样:

@pytest.mark.skipif(pytest.global_env in 'prod',
                reason="feature not in Prod yet")

但是,每当我针对产品运行测试时,它们都不会被跳过。我做了些摆弄,发现:

a)可以通过另一个固定装置访问global_env变量

@pytest.fixture(scope="session", autouse=True)
def mod_header(request):
    log.info('\n-----\n| '+pytest.global_env+' |\n-----\n')

在我的日志中正确显示

b)可以在测试中访问global_env变量,从而正确记录环境。

c)pytest_namespace已弃用

所以,我假设这与skipif访问global_env时的情况有关,与夹具在测试会话中进行时的情况有关。我也发现使用不推荐使用的功能是不理想的。

我的问题是:

  • 如何从pytest命令行选项中获取一个值作为小记号?
  • 有没有比pytest_namespace更好的方法了?

2 个答案:

答案 0 :(得分:2)

将全局代码放入夹具中的问题在于,在夹具之前先评估标记,因此在评估skipif时,configInfo尚未运行,而pytest.global_env将为空。我建议将配置代码从夹具移至pytest_configure钩子:

# conftest.py
import configparser
import pytest


def pytest_addoption(parser):
    parser.addoption('--ENV')


def pytest_configure(config):
    environment = config.getoption('--ENV')
    pytest.global_env = environment
    ...

确保在收集测试和评估标记之前执行配置挂钩。

  

有比pytest_namespace更好的方法了吗?

我知道的一些方式:

  1. 只需在pytest_configure中分配一个模块变量即可(pytest.foo = 'bar',就像我在上面的示例中所做的那样。)
  2. 使用config对象,因为它在整个测试会话中是共享的:

    def pytest_configure(config):
        config.foo = 'bar'
    
    @pytest.fixture
    def somefixture(pytestconfig):
        assert pytestconfig.foo == 'bar'
    
    def test_foo(pytestconfig):
        assert pytestconfig.foo == 'bar'
    

    在固定装置/测试之外,您可以通过pytest.config访问配置,例如:

    @pytest.mark.skipif(pytest.config.foo == 'bar', reason='foo is bar')
    def test_baz():
        ...
    
  3. 使用caching;这具有在测试运行之间持久保存数据的附加功能:

    def pytest_configure(config):
        config.cache.set('foo', 'bar')
    
    @pytest.fixture
    def somefixture(pytestconfig):
        assert pytestconfig.cache.get('foo', None)
    
    def test_foo(pytestconfig):
        assert pytestconfig.cache.get('foo', None)
    
    @pytest.mark.skipif(pytest.config.cache.get('foo', None) == 'bar', reason='foo is bar')
    def test_baz():
        assert True
    

使用1.或2.时,请确保不要无意间用自己的数据覆盖pytest内容;给您自己的变量加上唯一的名称是一个好主意。使用缓存时,您没有这个问题。

答案 1 :(得分:0)

看起来像去Control skipping of tests according to command line option的真实方法是将测试动态标记为 skip

  1. 使用 pytest_addoption 钩子添加选项,如下所示:

    def pytest_addoption(parser): parser.addoption( "--runslow", action="store_true", default=False, help="run slow tests" )

  2. 使用 pytest_collection_modifyitems 钩子添加标记,如下所示:

    def pytest_collection_modifyitems(config, items): if config.getoption("--runslow"): # --runslow given in cli: do not skip slow tests return skip_slow = pytest.mark.skip(reason="need --runslow option to run") for item in items: if "slow" in item.keywords: item.add_marker(skip_slow)

  3. 为您的测试添加标记:

    @pytest.mark.slow def test_func_slow(): pass

例如,如果您想在测试中使用CLI中的数据,则为凭据,足以在从{{3}检索数据时指定skip option }:

  1. 使用 pytest_addoption 钩子添加选项,如下所示:

    def pytest_addoption(parser): parser.addoption( "--credentials", action="store", default=None, help="credentials to ..." )

  2. 从pytestconfig获取
  3. 使用 skip 选项

    @pytest.fixture(scope="session") def super_secret_fixture(pytestconfig): credentials = pytestconfig.getoption('--credentials', skip=True) ...

  4. 在测试中照常使用夹具:

    def test_with_fixture(super_secret_fixture): ...

在这种情况下,您将收到类似的内容,而不将--credentials选项发送到CLI: Skipped: no 'credentials' option found

最好使用pytestconfig而不推荐使用 pytest.config 。如果您仍然不愿意像这样使用_pytest.config.get_config@pytest.mark.skipif(not _pytest.config.get_config().getoption('--credentials'), reason="--credentials was not specified")