如何正确导入测试类以继承自,而不是 运行 作为测试
How can I import a testclass properly to inherit from, without it being run as a test
上下文
我有一个测试 class,我的所有测试都继承自该测试。它本身不能运行,因为它实际上不包含任何设置信息
我想添加一个由所有测试执行的测试(将其添加到基础class 似乎合乎逻辑)
但现在我注意到我导入的 basetestclass( => Foo) 被检测为测试本身和 运行s 并且在报告中可见
代码
基础 class 在 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
真正的考验在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
这会触发对导入的 Foo
的测试运行
问题
如何导入 Foo 而不会被检测为 'test'
如果我在所有测试中删除 运行 的测试,一切都很好。
向 Foo 添加 @nottest
装饰器将无法工作,从那时起所有继承的 classes 都被定义为 nottest。
它需要 运行 nose
、pytest
和 unittest
测试 运行 人
我注意到如果我像下面这样更改导入语句,它也会起作用。但这意味着要在不同的回购协议中调整数百个测试文件。 (我想避免这种情况)
import base
class TestFoo(base.Foo):
答案的关键似乎是每个测试都有一个属性__test__
,当它是测试时设置为True
。
当 class 不应该是测试时将其设置为 False
将让测试收集器忽略此 class。
答案假定我只能在 base.py
中进行更改
在 python 3.9 中 class 方法和 属性 装饰器可以组合,所以我为此写了一个单独的答案
< py3.9 的答案
基础 class 在 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
基础 class 在 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 的测试运行
上下文
我有一个测试 class,我的所有测试都继承自该测试。它本身不能运行,因为它实际上不包含任何设置信息
我想添加一个由所有测试执行的测试(将其添加到基础class 似乎合乎逻辑)
但现在我注意到我导入的 basetestclass( => Foo) 被检测为测试本身和 运行s 并且在报告中可见
代码
基础 class 在 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
真正的考验在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
这会触发对导入的 Foo
的测试运行问题
如何导入 Foo 而不会被检测为 'test' 如果我在所有测试中删除 运行 的测试,一切都很好。
向 Foo 添加 @nottest
装饰器将无法工作,从那时起所有继承的 classes 都被定义为 nottest。
它需要 运行 nose
、pytest
和 unittest
测试 运行 人
我注意到如果我像下面这样更改导入语句,它也会起作用。但这意味着要在不同的回购协议中调整数百个测试文件。 (我想避免这种情况)
import base
class TestFoo(base.Foo):
答案的关键似乎是每个测试都有一个属性__test__
,当它是测试时设置为True
。
当 class 不应该是测试时将其设置为 False
将让测试收集器忽略此 class。
答案假定我只能在 base.py
中进行更改在 python 3.9 中 class 方法和 属性 装饰器可以组合,所以我为此写了一个单独的答案
< py3.9 的答案
基础 class 在 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
基础 class 在 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 的测试运行