使用带有py.test参数化的子类

时间:2015-06-24 02:24:56

标签: python decorator pytest

我有一个场景,能够在py.test中对基础测试类进行子类化,这将使我们的测试环境具有很强的可扩展性。我遇到的问题是我无法覆盖基类的属性并在参数化装饰器中使用它们。

import pytest

class TestBase():
    l = [2,3]

    @pytest.mark.parametrize('p', l)
    def testOne(self, p):
        assert p == p

class TestSubClass(TestBase):
    l = [1, 2, 3, 4]

class TestSubClass2(TestBase):
    l = [3, 5]

在此方案中,TestSubClassTestSubClass2始终使用l中的列表TestBase运行,因为装饰器查找l的范围是本地的范围。

我无法使用self.l,因为在评估装饰器时self不存在(没有实例)。

我可以解决这个问题并在测试用例中手动执行参数化,但后来我丢失了py.test的单独报告。例如

import pytest
class TestBase()
    def testOne(self):
        for p in self.l:
            assert p == p

class TestSubClass(TestBase):
    l = [1, 2, 3, 4]

class TestSubClass2(TestBase):
    l = [3, 5]

如何对基类进行子类化并为每个子类自定义参数化?

1 个答案:

答案 0 :(得分:0)

我有一个轻微可怕的解决方案:

  1. 更改基类,使列表成为所有可能选项的超集。
  2. 在收集时,py.test构建所有可能的测试列表
  3. 在运行时检查参数的值是否为该基类的有效值。如果不是,请跳过测试
  4. 代码:

    import pytest
    
    class TestBase():
        l = [1, 2, 3, 4, 5]
    
        @pytest.mark.parametrize('p', l)
        def testOne(self, p):
            if p not in self.l:
                pytest.skip("%d not supported on %s" % (p, self.__class__.__name__))
            assert p == p
    
    class TestSubClass(TestBase):
        l = [1, 2]
    
    class TestSubClass2(TestBase):
        l = [3, 5]
    

    和相应的输出:

    py.test -v -rsf test_sample.py::TestSubClass
    ===================================== test session starts ======================================
    platform darwin -- Python 2.7.9 -- py-1.4.26 -- pytest-2.6.4 -- 
    collected 5 items 
    
    test_sample.py::TestSubClass::testOne[1] PASSED
    test_sample.py::TestSubClass::testOne[2] PASSED
    test_sample.py::TestSubClass::testOne[3] SKIPPED
    test_sample.py::TestSubClass::testOne[4] SKIPPED
    test_sample.py::TestSubClass::testOne[5] SKIPPED
    =================================== short test summary info ====================================
    SKIP [1] test_sample.py:10: 4 not supported on TestSubClass
    SKIP [1] test_sample.py:10: 3 not supported on TestSubClass
    SKIP [1] test_sample.py:10: 5 not supported on TestSubClass
    
    ============================= 2 passed, 3 skipped in 0.01 seconds ==============================
    

    这种方法会带来一些可怕的后果:

    • 为新子类添加单个特定案例需要将其添加到子类和基类
    • 如果您没有将特定案例添加到基类,它将默默无法运行它。
    • 在你跳跃之前,测试用例需要额外的一些额外的帮助。开始时的代码以确定它是否是有效的测试用例