TL;DR
你可以跳过测试本身的条件;跳到答案末尾的Suggestion。使用您的示例代码,无法通过 skipIf 标记跳过测试。
首先我要明确一点:如果你定义了一个返回值的autouse fixturefoo,并不意味着测试类会自动变成属性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的支持是有限的。不知道你为什么需要上课;您可以仅使用夹具在多个测试功能之间完美共享状态。 pytest 的全部目的是使测试类过时,每个测试方法都可以重新设计为测试函数。
如果您需要在一个类中的测试之间共享一个值,您需要将它分配给夹具中测试类实例的某个属性。下面的例子会通过:
class TestCls:
@pytest.fixture(autouse=True)
def fix(self):
self._fix = 'foo'
def test_fix(self):
assert self._fix == 'foo'
因此,实际上返回某些东西的夹具在测试类中是没有用的,因为没有办法将夹具作为参数传递给测试类方法。
不知道为什么上课失败
这是因为在测试集合上评估标记以过滤出应该执行的测试,并且仅在测试收集并准备好运行之后执行夹具。这意味着你想要的东西是不可能的。您将无法将任何夹具结果传递给skipif 标记,因为尚未评估任何夹具。查看执行顺序:
@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