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

如何在不作为测试运行的情况下正确导入测试类以从中继承

  •  0
  • studioj  · 技术社区  · 5 年前

    上下文

    我有一个测试类,我的所有测试都继承自该类。它不能自己运行,因为它实际上不包含任何设置信息

    我想添加一个由所有测试执行的测试(将它添加到基类似乎是合乎逻辑的)

    但现在我注意到我导入的basetestclass(=>Foo)被检测为测试本身并运行,并且在报告中可见

    密码

    base.py中的基类

    from unittest import TestCase
    
    class Foo(TestCase):
        @classmethod
        def setUpClass(cls):
            # prepare the generic setup stuff based on what is defined in the child class
            print("setupclass Foo done")
    
        def test_run_in_all_inherited_tests(self):
            print("fooBar")
            assert True
    

    testsomething.py中的真实测试

    from base import Foo # <= This is being detected as a testclass object and thus will be executed
    
    class TestFoo(Foo):
        @classmethod
        def setUpClass(cls):
            # define specific test setup
            super().setUpClass()
            print("setup TestFoo done")
    
        def test_pass(self):
            pass
    
        def test_assert(self):
            assert False
    

    这将触发导入Foo的测试运行

    pycharm testrun

    问题

    如何导入Foo而不将其检测为“测试” 如果我删除测试以在所有测试中运行,一切都很好。

    正在添加 @nottest 从那时起,Foo的decorator就不起作用了——所有继承的类都被定义为nottest。

    它需要继续运行 nose , pytest unittest 试车员

    我注意到,如果我像下面这样更改导入语句,它也会起作用。但这意味着要调整不同转发中的数百个测试文件。(我想避免这种情况)

    import base
    class TestFoo(base.Foo):
    
    0 回复  |  直到 5 年前
        1
  •  5
  •   studioj    5 年前

    答案的关键似乎是每个测试都有一个属性 __test__ 设置为 True 当它是一个测试。

    将其设置为 False 当该类不应该是测试时,将让测试收集器忽略该类。

    答案假设我只能在base.py中进行更改

    在python 3.9中,类方法和属性装饰器可以组合在一起,所以我为此写了一个单独的答案

    回答<py3.9

    base.py中的基类

    from unittest import TestCase
    
    class MetaFoo(type):
        @property
        def __test__(cls):
            return cls != Foo
    
    class Foo(TestCase, metaclass=MetaFoo):
        @classmethod
        def setUpClass(cls):
            # prepare the generic setup stuff based on what is defined in the child class
            print("setupclass Foo done")
    
        def test_run_in_all_inherited_tests(self):
            print("fooBar")
            assert True
    

    回答>=py3.9

    base.py中的基类

    from unittest import TestCase
    
    class Foo(TestCase):
        @classmethod
        @property
        def __test__(cls):
            return cls != Foo
    
        @classmethod
        def setUpClass(cls):
            # prepare the generic setup stuff based on what is defined in the child class
            print("setupclass Foo done")
    
        def test_run_in_all_inherited_tests(self):
            print("fooBar")
            assert True
    

    实际测试

    test_something.py

    from base import Foo # <= This will not be detected as a test anymore as __test__ returns False
    
    class TestFoo(Foo):
        @classmethod
        def setUpClass(cls):
            # define specific test setup
            super().setUpClass()
            print("setup TestFoo done")
    
        def test_pass(self):
            pass
    
        def test_assert(self):
            assert False
    

    这不再触发导入Foo的测试运行 pycharm test run