stu*_*ioj 5 python inheritance nose pytest python-unittest
我有一个测试类,我的所有测试都继承自该类。它无法自行运行,因为它实际上不包含任何设置信息
我想添加一个由所有测试执行的测试(将其添加到基类似乎合乎逻辑)
但现在我注意到我导入的 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
Run Code Online (Sandbox Code Playgroud)
真正的测试在 test_something.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
Run Code Online (Sandbox Code Playgroud)
这会触发导入的 Foo 的测试运行
如何导入 Foo 而不将其检测为“测试”如果我删除测试以在所有测试中运行,一切都很好。
向 Foo添加@nottest
装饰器将不起作用,因为所有继承的类都被定义为非测试。
它需要在nose
,pytest
和unittest
测试运行器上运行
我注意到,如果我像下面这样更改导入语句,它也可以工作。但这意味着需要调整不同存储库中的数百个测试文件。(我想避免这种情况)
import base
class TestFoo(base.Foo):
Run Code Online (Sandbox Code Playgroud)
答案的关键似乎是每个测试都有一个在测试时__test__
设置的属性。True
将其设置为False
当类不应该是测试时将使测试收集器忽略此类。
答案假设我只能在 base.py 中进行更改
在 python 3.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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)