Python 通过子类化 TestCase 参数化单元测试
Python parameterized unittest by subclassing TestCase
如何以编程方式创建多个测试用例并运行它们?我正在尝试在一个常见的 TestCase 上测试一个集合的多个实现。
我更愿意坚持使用简单的单元测试并避免依赖。
以下是我查看的一些资源,但并不完全符合我的要求:
Writing a re-usable parametrized unittest.TestCase method - 接受的答案提出了四个不同的外部库。
http://eli.thegreenplace.net/2011/08/02/python-unit-testing-parametrized-test-cases -
这种方法使用静态方法 paramerize
。不明白为什么不能直接传入参数
TestSubClass.__init__
.
How to generate dynamic (parametrized) unit tests in python? - 有点太黑魔法了。
这是一个最小的(非)工作示例。
import unittest
MyCollection = set
AnotherCollection = set
# ... many more collections
def maximise(collection, array):
return 2
class TestSubClass(unittest.TestCase):
def __init__(self, collection_class):
unittest.TestCase.__init__(self)
self.collection_class = collection_class
self.maximise_fn = lambda array: maximise(collection_class, array)
def test_single(self):
self.assertEqual(self.maximise_fn([1]), 1)
def test_overflow(self):
self.assertEqual(self.maximise_fn([3]), 1)
# ... many more tests
def run_suite():
suite = unittest.defaultTestLoader
for collection in [MyCollection, AnotherCollection]:
suite.loadTestsFromTestCase(TestSubClass(collection))
unittest.TextTestRunner().run(suite)
def main():
run_suite()
if __name__ == '__main__':
main()
上述方法错误在 loadTestsFromTestCase
:
TypeError: issubclass() arg 1 must be a class
如何使用pytest
with to parametrize fixture:
import pytest
MyCollection = set
AnotherCollection = set
def maximise(collection, array):
return 1
@pytest.fixture(scope='module', params=[MyCollection, AnotherCollection])
def maximise_fn(request):
return lambda array: maximise(request.param, array)
def test_single(maximise_fn):
assert maximise_fn([1]) == 1
def test_overflow(maximise_fn):
assert maximise_fn([3]) == 1
如果这不是一个选项,您可以创建一个包含测试函数的混合,并创建子类以提供 maximise_fn
s:
import unittest
MyCollection = set
AnotherCollection = set
def maximise(collection, array):
return 1
class TestCollectionMixin:
def test_single(self):
self.assertEqual(self.maximise_fn([1]), 1)
def test_overflow(self):
self.assertEqual(self.maximise_fn([3]), 1)
class TestMyCollection(TestCollectionMixin, unittest.TestCase):
maximise_fn = lambda self, array: maximise(MyCollection, array)
class TestAnotherCollection(TestCollectionMixin, unittest.TestCase):
maximise_fn = lambda self, array: maximise(AnotherCollection, array)
if __name__ == '__main__':
unittest.main()
如何以编程方式创建多个测试用例并运行它们?我正在尝试在一个常见的 TestCase 上测试一个集合的多个实现。
我更愿意坚持使用简单的单元测试并避免依赖。
以下是我查看的一些资源,但并不完全符合我的要求:
Writing a re-usable parametrized unittest.TestCase method - 接受的答案提出了四个不同的外部库。
http://eli.thegreenplace.net/2011/08/02/python-unit-testing-parametrized-test-cases - 这种方法使用静态方法
paramerize
。不明白为什么不能直接传入参数TestSubClass.__init__
.How to generate dynamic (parametrized) unit tests in python? - 有点太黑魔法了。
这是一个最小的(非)工作示例。
import unittest
MyCollection = set
AnotherCollection = set
# ... many more collections
def maximise(collection, array):
return 2
class TestSubClass(unittest.TestCase):
def __init__(self, collection_class):
unittest.TestCase.__init__(self)
self.collection_class = collection_class
self.maximise_fn = lambda array: maximise(collection_class, array)
def test_single(self):
self.assertEqual(self.maximise_fn([1]), 1)
def test_overflow(self):
self.assertEqual(self.maximise_fn([3]), 1)
# ... many more tests
def run_suite():
suite = unittest.defaultTestLoader
for collection in [MyCollection, AnotherCollection]:
suite.loadTestsFromTestCase(TestSubClass(collection))
unittest.TextTestRunner().run(suite)
def main():
run_suite()
if __name__ == '__main__':
main()
上述方法错误在 loadTestsFromTestCase
:
TypeError: issubclass() arg 1 must be a class
如何使用pytest
with to parametrize fixture:
import pytest
MyCollection = set
AnotherCollection = set
def maximise(collection, array):
return 1
@pytest.fixture(scope='module', params=[MyCollection, AnotherCollection])
def maximise_fn(request):
return lambda array: maximise(request.param, array)
def test_single(maximise_fn):
assert maximise_fn([1]) == 1
def test_overflow(maximise_fn):
assert maximise_fn([3]) == 1
如果这不是一个选项,您可以创建一个包含测试函数的混合,并创建子类以提供 maximise_fn
s:
import unittest
MyCollection = set
AnotherCollection = set
def maximise(collection, array):
return 1
class TestCollectionMixin:
def test_single(self):
self.assertEqual(self.maximise_fn([1]), 1)
def test_overflow(self):
self.assertEqual(self.maximise_fn([3]), 1)
class TestMyCollection(TestCollectionMixin, unittest.TestCase):
maximise_fn = lambda self, array: maximise(MyCollection, array)
class TestAnotherCollection(TestCollectionMixin, unittest.TestCase):
maximise_fn = lambda self, array: maximise(AnotherCollection, array)
if __name__ == '__main__':
unittest.main()