UnitTest.TestCase支持

pytest 支持运行python unittest -开箱即用的测试。它是为了利用现有的 unittest -基于测试套件,将pytest用作测试运行程序,还允许增量调整测试套件,以充分利用pytest的特性。

运行现有的 unittest -样式测试套件使用 pytest 类型:

pytest tests

Pytest将自动收集 unittest.TestCase 子类及其 test 方法在 test_*.py*_test.py 文件夹。

几乎所有 unittest 支持以下功能:

  • @unittest.skip 风格装饰符;

  • setUp/tearDown

  • setUpClass/tearDownClass

  • setUpModule/tearDownModule

到目前为止,pytest不支持以下功能:

  • load_tests protocol

  • subtests

开箱即用的好处

通过使用pytest运行测试套件,您可以使用多个功能,在大多数情况下,无需修改现有代码:

中的pytest功能 unittest.TestCase 子类

以下Pytest功能适用于 unittest.TestCase 子类:

以下Pytest功能 工作,可能永远不会由于不同的设计理念:

第三方插件可能工作得不好,这取决于插件和测试套件。

将比重测试夹具混合到 unittest.TestCase 使用标记的子类

使用运行UnitTest pytest 允许您使用 fixture mechanism 具有 unittest.TestCase 风格测试。假设您至少略过了pytest fixture的特性,那么让我们从一个集成了pytest的示例开始。 db_class fixture,设置一个类缓存的数据库对象,然后从unittest样式测试引用它:

# content of conftest.py

# we define a fixture function below and it will be "used" by
# referencing its name from tests

import pytest


@pytest.fixture(scope="class")
def db_class(request):
    class DummyDB:
        pass

    # set a class attribute on the invoking test context
    request.cls.db = DummyDB()

这定义了一个fixture函数 db_class 如果使用,每个测试类调用一次,并设置类级别 db 属性为 DummyDB 实例。fixture函数通过接收一个特殊的 request 允许访问的对象 the requesting test contextcls 属性,表示从中使用设备的类。该体系结构将实际测试代码中的fixture编写分离开来,并允许通过最小的引用(fixture名称)重用fixture。那么让我们写一个 unittest.TestCase 使用我们的fixture定义初始化:

# content of test_unittest_db.py

import unittest
import pytest


@pytest.mark.usefixtures("db_class")
class MyTest(unittest.TestCase):
    def test_method1(self):
        assert hasattr(self, "db")
        assert 0, self.db  # fail for demo purposes

    def test_method2(self):
        assert 0, self.db  # fail for demo purposes

这个 @pytest.mark.usefixtures("db_class") 类decorator确保pytest fixture函数 db_class 每个类调用一次。由于故意失败的断言语句,我们可以查看 self.db 回溯中的值:

$ pytest test_unittest_db.py
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 2 items

test_unittest_db.py FF                                               [100%]

================================= FAILURES =================================
___________________________ MyTest.test_method1 ____________________________

self = <test_unittest_db.MyTest testMethod=test_method1>

    def test_method1(self):
        assert hasattr(self, "db")
>       assert 0, self.db  # fail for demo purposes
E       AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
E       assert 0

test_unittest_db.py:10: AssertionError
___________________________ MyTest.test_method2 ____________________________

self = <test_unittest_db.MyTest testMethod=test_method2>

    def test_method2(self):
>       assert 0, self.db  # fail for demo purposes
E       AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
E       assert 0

test_unittest_db.py:13: AssertionError
========================= short test summary info ==========================
FAILED test_unittest_db.py::MyTest::test_method1 - AssertionError: <conft...
FAILED test_unittest_db.py::MyTest::test_method2 - AssertionError: <conft...
============================ 2 failed in 0.12s =============================

这个默认的pytest回溯显示两个测试方法共享相同的 self.db 在编写上面的类范围fixture函数时,我们打算使用的实例。

使用自动使用设备并访问其他设备

尽管在给定的测试中显式地声明所需的fixture的使用通常更好,但有时您可能希望在给定的上下文中自动使用fixture。毕竟,传统风格的UnitTest设置要求使用这种隐式的fixture编写,机会是,你习惯了它或者喜欢它。

可以用标记fixture函数 @pytest.fixture(autouse=True) 并在您想要使用的上下文中定义fixture函数。让我们看看 initdir 使所有试验方法 TestCase 类在临时目录中执行,并预先初始化 samplefile.ini . 我们的 initdir fixture本身使用pytest内置 tmpdir 委托创建每个测试临时目录的fixture:

# content of test_unittest_cleandir.py
import pytest
import unittest


class MyTest(unittest.TestCase):
    @pytest.fixture(autouse=True)
    def initdir(self, tmpdir):
        tmpdir.chdir()  # change to pytest-provided temporary directory
        tmpdir.join("samplefile.ini").write("# testdata")

    def test_method(self):
        with open("samplefile.ini") as f:
            s = f.read()
        assert "testdata" in s

由于 autouse 国旗 initdir fixture函数将用于定义它的类的所有方法。这是使用 @pytest.mark.usefixtures("initdir") 类上的标记,如前一个示例中所示。

运行此测试模块…:

$ pytest -q test_unittest_cleandir.py
.                                                                    [100%]
1 passed in 0.12s

…给了我们一次通过测试,因为 initdir fixture函数在 test_method .

注解

unittest.TestCase 方法不能直接接收fixture参数,因为实现可能会影响运行常规unittest.testcase测试套件的能力。

以上 usefixturesautouse 示例应该有助于将Pytest夹具混合到UnitTest套件中。

您也可以逐渐远离子类化 unittest.TestCase简单断言 然后开始逐步受益于完整的pytest特性集。

注解

由于两个框架之间的体系结构差异,为 unittest -基础测试在 call 测试阶段而不是 pytest 标准 setupteardown 阶段。在某些情况下,理解这一点很重要,尤其是在推理错误时。例如,如果 unittest -基于套件在设置期间显示错误, pytest 将在其 setup 并将在 call .