python - Pytest 无法通过标记 skipif 跳过类中的测试用例

标签 python unit-testing testing pytest

我正在使用 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/

相关文章:

python - 在对数刻度轴上设置自定义标签的格式

python - 转义 MySQL LOAD DATA INFILE 命令

unit-testing - Microsoft Visual Studio 测试导致测试失败

python - 为什么在测试中没有将查询添加到 Django 的 db.connection.queries 中?

c++ - 如何比较谷歌模拟中的特殊领域?

python - 我如何使用 lxml , python 解析 html

python - 了解虚拟环境行为

unit-testing - 测试自耕农的 composeWith

c++ - 使用谷歌模拟测试 C++ 时无法推断模板参数

python - 使用 Pytest 测试 Python 程序