我正在使用 pytest 框架并希望根据某些条件跳过测试用例。下面的代码没有跳过测试用例。
import pytest
class TEST:
@pytest.fixture(scope="function", autouse=True)
def func_fixture(self):
return "fail"
@pytest.mark.skipif("self.func_fixture=='fail'")
def test_setting_value(self):
print("Hello I am in testcase")
运行时,它说执行了 0 个测试用例。
这个func_fixture
对测试套件非常重要。它在开始测试之前执行许多先决条件。
如果我删除类,并使用相同的语法添加其余函数(在删除 self 之后),它会起作用。不知道为什么它在类里面不及格
最佳答案
长话短说
您可以跳过测试本身的条件;跳到答案末尾的建议。使用您的示例代码,不可能通过 skipIf
标记跳过测试。
首先,让我明确以下几点:如果你定义一个返回值的autouse fixture foo
,并不意味着测试类会自动成为一个属性foo
.
class TestCls:
@pytest.fixture(autouse=True)
def fix(self):
return 'foo'
def test_fix(self):
assert self.fix == 'foo'
运行此测试将失败:
def test_fix(self):
> assert self.fix == 'foo'
E AssertionError: assert <bound method TestCls.fix of <test_bacon.TestCls object at 0x105670cf8>> == 'foo'
E + where <bound method TestCls.fix of <test_bacon.TestCls object at 0x105670cf8>> = <test_bacon.TestCls object at 0x105670cf8>.fix
那是因为固定装置不是这样工作的。如果 fixture 正在返回某些东西,如果在测试函数中添加一个与 fixture 同名的参数,就可以访问它的返回值。这是类的问题,因为您不能将固定装置作为参数传递给测试类方法;总体而言,pytest
中对测试classes 的支持是有限的。完全不确定为什么需要类(class);您可以单独使用固定装置在多个测试功能之间完美共享状态。 pytest
的全部意图是让测试类过时,其中每个测试方法都可以重新编写为测试函数。
如果您需要在类中的测试之间共享一个值,则需要将其分配给 fixture 中测试类实例的某个属性。下面的例子将通过:
class TestCls:
@pytest.fixture(autouse=True)
def fix(self):
self._fix = 'foo'
def test_fix(self):
assert self._fix == 'foo'
因此,实际上返回某些东西的固定装置在测试类中是无用的,因为无法将固定装置作为测试类方法中的参数传递。
Not sure why it is failing in class
这是因为标记是在测试集合上评估的,以过滤掉应该执行的测试,并且只有测试被收集并准备好运行后才会执行固定装置。这意味着你想要的是不可能的。您将无法将任何 fixture 结果传递给 skipif
标记,因为尚未评估任何 fixture 。查看执行顺序:
@pytest.fixture(autouse=True)
def myfixture():
print('myfixture called')
class TestCls:
@pytest.fixture(autouse=True)
def myclassfixture(self):
print('TestCls.myclassfixture called')
@pytest.mark.skipif('print(os.linesep, "TestCls.test_spam skipif called")', reason='something')
def test_spam(self):
print('TestCls.test_spam called')
输出:
TestCls.test_spam skipif called
myfixture called
TestCls.myclassfixture called
TestCls.test_spam called
另请注意,测试类实例在 skipif
中不可用,只有在模块级别定义的实例(类、函数和全局变量):
class Tests:
@pytest.mark.skipif('print(os.linesep, "globals:", globals().keys(), os.linesep, "locals:", locals().keys())', reason='something')
def test_spam(self):
pass
输出:
test_spam.py::TestCls::test_spam
globals: dict_keys(['os', 'sys', 'platform', 'config', '__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', '@py_builtins', '@pytest_ar', 'pytest', 'myfixture', 'TestCls'])
locals: dict_keys(['os', 'sys', 'platform', 'config', '__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', '@py_builtins', '@pytest_ar', 'pytest', 'myfixture', 'TestCls'])
建议
除了 skip
/skipIf
标记之外,您还可以在测试本身内显式跳过测试:
class TestCls:
@pytest.fixture(autouse=True)
def myfixture(self):
self.status = 'fail'
def test_eggs(self):
if self.status == 'fail':
pytest.skip('self.status is set to "fail"')
assert False
如果运行,则跳过测试:
test_eggs.py::TestCls::test_eggs SKIPPED
关于python - Pytest 无法通过标记 skipif 跳过类中的测试用例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51760917/