如何测试 pytest 夹具是否引发异常?

2023-12-30

使用案例:在一个pytest测试套件我有一个@fixture如果缺少配置的命令行选项,则会引发异常。我已经使用这个夹具编写了一个测试xfail:

import pytest
from <module> import <exception>

@pytest.mark.xfail(raises=<exception>)
def test_fixture_with_missing_options_raises_exception(rc_visard):
    pass

然而,运行测试后的输出并不表明测试已通过,而是“xfailed”:

============================== 1 xfailed in 0.15 seconds ========================

除此之外,我无法测试是否fixture引发特定缺失命令行选项的异常。

有更好的方法来做到这一点吗?我可以嘲笑pytest命令行选项不知何故我不需要通过调用特定的测试pytest --<commandline-option-a> <test-file-name>::<test-name>.


初始设置

假设您有一个简化的项目conftest.py包含以下代码:

import pytest


def pytest_addoption(parser):
    parser.addoption('--foo', action='store', dest='foo', default='bar',
                     help='--foo should be always bar!')

@pytest.fixture
def foo(request):
    fooval = request.config.getoption('foo')
    if fooval != 'bar':
        raise ValueError('expected foo to be "bar"; "{}" provided'.format(fooval))

它添加了一个新的命令行参数--foo和一个固定装置foo返回传递的参数,或者bar如果没有指定。如果除此之外还有什么bar通过--foo,夹具产生ValueError.

例如,您可以像往常一样使用灯具

def test_something(foo):
    assert foo == 'bar'

现在让我们测试一下该装置。

准备工作

在这个例子中,我们首先需要进行一些简单的重构。将夹具和相关代码移动到某个名为其他名称的文件中conftest.py, 例如,my_plugin.py:

# my_plugin.py

import pytest


def pytest_addoption(parser):
    parser.addoption('--foo', action='store', dest='foo', default='bar',
                     help='--foo should be always bar!')

@pytest.fixture
def foo(request):
    fooval = request.config.getoption('foo')
    if fooval != 'bar':
        raise ValueError('expected foo to be "bar"; "{}" provided'.format(fooval))

In conftest.py,确保新插件已加载:

# conftest.py

pytest_plugins = ['my_plugin']

运行现有的测试套件以确保我们没有破坏任何东西,所有测试仍然应该通过。

启用pytester

pytest提供了一个额外的插件用于编写插件测试,称为pytester。默认情况下它不会激活,因此您应该手动执行此操作。在conftest.py,扩展插件列表pytester:

# conftest.py

pytest_plugins = ['my_plugin', 'pytester']

编写测试

Once pytester处于活动状态,您将获得一个名为testdir。它可以生成并运行pytest来自代码的测试套件。我们的第一个测试如下所示:

# test_foo_fixture.py

def test_all_ok(testdir):

    testdata = '''
               def test_sample(foo):
                   assert True
               '''

    testconftest = '''
                   pytest_plugins = ['my_plugin']
                   '''

    testdir.makeconftest(testconftest)
    testdir.makepyfile(testdata)
    result = testdir.runpytest()
    result.assert_outcomes(passed=1)

这里发生的事情应该非常明显:我们以字符串形式提供测试代码,testdir将生成一个pytest从它的项目到某个临时目录。为确保我们的fooFixture 在生成的测试项目中可用,我们将其传递到生成的测试项目中conftest和我们在真人中做的一样。testdir.runpytest()开始测试运行,产生我们可以检查的结果。

让我们添加另一个测试来检查是否foo将提出一个ValueError:

def test_foo_valueerror_raised(testdir):
    testdata = '''
               def test_sample(foo):
                   assert True
               '''

    testconftest = '''
                   pytest_plugins = ['my_plugin']
                   '''

    testdir.makeconftest(testconftest)
    testdir.makepyfile(testdata)
    result = testdir.runpytest('--foo', 'baz')                                                                                                                                
    result.assert_outcomes(errors=1)
    result.stdout.fnmatch_lines([
        '*ValueError: expected foo to be "bar"; "baz" provided'
    ])

在这里我们执行生成的测试--foo baz并随后验证一项测试是否以错误结束,并且错误输出是否包含预期的错误消息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何测试 pytest 夹具是否引发异常? 的相关文章

随机推荐