代码之家  ›  专栏  ›  技术社区  ›  NI6

pytest中的分组测试:类与普通函数

  •  56
  • NI6  · 技术社区  · 6 年前

    我正在使用pytest测试我的应用程序。 pytest支持两种编写测试的方法(我知道):

    1. 课堂上:

    test\u功能。py->类TestFeature->def test\u feature\u健全性

    1. 在函数中:

    test\u功能。py->def test\u feature\u健全性

    是否需要在类中分组测试的方法?是否允许对内置模块进行单元测试? 你认为哪种方法更好?为什么?

    4 回复  |  直到 4 年前
        1
  •  55
  •   Zim    6 年前

    关于将测试组织到模块和类中,没有严格的规则。这是个人喜好的问题。起初,我尝试将测试组织到课堂上,过了一段时间,我意识到我没有必要再组织其他级别的测试。现在我只是将测试函数收集到模块(文件)中。

    我可以看到一个有效的用例,当一些测试可以逻辑地组织到同一个文件中,但仍然有其他级别的组织到类中(例如使用类范围的fixture)。但也可以将其拆分为多个模块。

        2
  •  49
  •   Jasha    3 年前

    这个答案为pytest中的TestClass提供了两个引人注目的用例:

    • 属于给定类别的多个测试方法的联合参数化。
    • 通过子类继承重用测试数据和测试逻辑

    属于给定类别的多个测试方法的联合参数化。

    pytest参数化修饰器, @pytest.mark.parametrize ,可用于将输入提供给类中的多个方法。在下面的代码中,输入 param1 param2 可用于每种方法 TestGroup.test_one TestGroup.test_two

    """test_class_parametrization.py"""
    import pytest
    
    @pytest.mark.parametrize(
        "param1,param2",
        [
            ("a", "b"),
            ("c", "d"),
        ],
    )
    class TestGroup:
        """A class with common parameters, `param1` and `param2`."""
    
        @pytest.fixture
        def fixt(self):
            """This fixture will only be available within the scope of TestGroup"""
            return 123
    
        def test_one(self, param1, param2, fixt):
            print("\ntest_one", param1, param2, fixt)
    
        def test_two(self, param1, param2):
            print("\ntest_two", param1, param2)
    
    $ pytest -s test_class_parametrization.py
    ================================================================== test session starts ==================================================================
    platform linux -- Python 3.8.6, pytest-6.2.1, py-1.10.0, pluggy-0.13.1
    rootdir: /home/jbss
    plugins: pylint-0.18.0
    collected 4 items
    
    test_class_parametrization.py
    test_one a b 123
    .
    test_one c d 123
    .
    test_two a b
    .
    test_two c d
    .
    
    =================================================================== 4 passed in 0.01s ===================================================================
    

    通过子类继承重用测试数据和测试逻辑

    我将使用以下代码的修改版本 another answer 演示从 TestClass TestSubclass :

    # in file `test_example.py`
    class TestClass:
        VAR = 3
        DATA = 4
    
        def test_var_positive(self):
            assert self.VAR >= 0
    
    
    class TestSubclass(TestClass):
        VAR = 8
    
        def test_var_even(self):
            assert self.VAR % 2 == 0
    
        def test_data(self):
            assert self.DATA == 4
    

    跑步 pytest 此文件上的原因 要运行的测试:

    $ pytest -v test_example.py
    =========== test session starts ===========
    platform linux -- Python 3.8.2, pytest-5.4.2, py-1.8.1
    collected 4 items
    
    test_example.py::TestClass::test_var_positive PASSED
    test_example.py::TestSubclass::test_var_positive PASSED
    test_example.py::TestSubclass::test_var_even PASSED
    test_example.py::TestSubclass::test_data PASSED
    

    在子类中,继承的 test_var_positive 方法使用更新的值运行 self.VAR == 8 ,以及新定义的 test_data 方法针对继承的属性运行 self.DATA == 4 。这种方法和属性继承提供了一种灵活的方法,可以重用或修改不同测试用例组之间的共享功能。

        3
  •  20
  •   mindthief    5 年前

    通常在单元测试中,测试的对象是单个函数。也就是说,一个函数产生多个测试。在通读测试代码时,以某种方式将单个单元的测试分组在一起是很有用的(这也允许我们运行特定功能的所有测试),因此我们有两个选择:

    1. 将每个功能的所有测试放在专用模块中
    2. 将每个函数的所有测试放在一个类中

    在第一种方法中,我们仍然有兴趣对与源模块相关的所有测试进行分组(例如。 utils.py )在某种程度上。现在,由于我们已经在使用模块对 作用 ,这意味着我们应该使用 包裹 对源模块的测试进行分组。

    结果是一个来源 作用 映射到一个测试 单元 ,和一个源 单元 映射到一个测试 包裹

    在第二种方法中,我们将有一个源函数映射到一个测试类(例如。 my_function() -&燃气轮机; TestMyFunction ),并将一个源模块映射到一个测试模块(例如。 UTIL。py公司 -&燃气轮机; test_utils.py )。

    这可能取决于具体情况,但第二种方法,即针对您正在测试的每个函数的一类测试,对我来说似乎更清楚。此外,如果我们正在测试源代码 类别 /方法,然后我们可以简单地使用测试类的继承层次结构,并且仍然保留一个源模块->一个测试模块映射。

    最后,与包含多个函数的测试的平面文件相比,这两种方法的另一个好处是,当类/模块已经识别出要测试的函数时,您可以为实际测试提供更好的名称,例如。 test_does_x test_handles_y 而不是 test_my_function_does_x test_my_function_handles_y

        4
  •  0
  •   Stefan    3 年前

    在JavaScript jasmine中,测试的结构是 描述 信息技术 方法: What is the difference between describe and it in Jest?

    下面是该概念的Python实现:

    https://pypi.org/project/pytest-describe/

    一个缺点可能是对IDE的支持滞后。 我想为了找到测试方法,他们的名字必须 以“test\uuu”开头,而不是“it\uu”

    def describe_list():
    
        @pytest.fixture
        def list():
            return []
    
        def describe_append():
    
            def adds_to_end_of_list(list):
                list.append('foo')
                list.append('bar')
                assert list == ['foo', 'bar']
    
        def describe_remove():
    
            @pytest.fixture
            def list():
                return ['foo', 'bar']
    
            def removes_item_from_list(list):
                list.remove('foo')
                assert list == ['bar']