目前我有许多类似的unittest TestCases。每个TestCase都包含数据(输入值+预期输出值)和逻辑(调用SUT并将实际输出与预期输出进行比较)。
我想将数据与逻辑分开。因此,我想要一个只包含逻辑的基类和一个只包含数据的派生类。到目前为止我想出了这个:
import unittest
class MyClass():
def __init__(self, input):
self.input = input
def get_result(self):
return self.input * 2
class TestBase(unittest.TestCase):
def check(self, input, expected_output):
obj = self.class_under_test(input)
actual_output = obj.get_result()
self.assertEqual(actual_output, expected_output)
def test_get_result(self):
for value in self.values:
self.check(value[0], value[1])
class TestMyClass(TestBase):
def __init__(self, methodName='runTest'):
unittest.TestCase.__init__(self, methodName)
self.class_under_test = MyClass
self.values = [(1, 2), (3, 6)]
unittest.main(exit = False)
但是这失败并出现以下错误:
AttributeError: 'TestBase' object has no attribute 'values'
两个问题:
答案 0 :(得分:6)
为了使这项工作符合预期,您至少需要:
__init__(self, methodName="runTest")
super(TestMyClass, self).__init__(methodName)
def test_get_result(self):
至于它是否是好的设计,请记住,您的测试部分作为您的代码工作方式的文档。如果你已经将所有工作隐藏在TestCase实例状态中,那么它的作用就不那么明显了。例如,编写一个具有自定义断言的mixin类可能会更好,这些断言可以获取输入和预期输出。
答案 1 :(得分:4)
设计(或多或少)很好 - 一个"打嗝"是当unittest查看所有 TestCase类并运行以" test"开头的方法时在他们。此时你有几个选择。
一种方法是指定测试中的类,并将值指定为类上的属性。在这里,如果可能的话,您希望这些值是不可变的......
class TestBase(unittest.TestCase):
def check(self, input, expected_output):
obj = self.class_under_test(input)
actual_output = obj.get_result()
self.assertEqual(actual_output, expected_output)
def check_all(self):
for value in self.values:
self.check(value[0], value[1])
class TestMyClass1(TestBase):
values = ((1, 2), (3, 4))
class_under_test = MyClass1
def test_it(self):
self.check_all()
class TestMyClass2(TestBase):
values = (('a', 'b'), ('d', 'e'))
class_under_test = MyClass2
def test_it(self):
self.check_all()
答案 2 :(得分:3)
你要两次test_get_result()
。我认为任何test*()
方法都不应该在TestBase
中。相反,使用TestBase
提供自定义断言,错误格式化程序,测试数据生成器等,并将实际测试保留在TestMyClass
中。
答案 3 :(得分:1)
这里有点晚了,但是最近需要进行单元测试继承
我能找到的最优雅的解决方案是:
首先-您需要一个基础测试类
class MyBaseUnitTest(unittest.TestCase):
__test__ = False
def test_someting(self):
...
def test_something_else(self):
...
然后继承该类并运行测试:
class TestA(MyBaseUnitTest):
__test__ = True
def test_feature(self):
pass
def test_feature2(self):
pass
这是拥有单个视图集继承的最佳,最简便的方法。
我发现多重继承的问题是,当您尝试调用诸如setUp()
之类的方法时,将不会在基础测试类上调用它,因此您必须在编写的扩展基础类的每个类中调用它
我希望这会在将来帮助某个人。
顺便说一句:这是在python3中完成的-我不知道它将如何在python2中做出反应
答案 4 :(得分:0)
Python的unittest.main()
执行当前命名空间中所有测试类的所有测试。
不直接在基类中运行测试的一种方法是将其移动到其他模块(例如将TestBase
移动到testbase.py
):
在调用unittest.main()
的文件中,请确保不要将该类导入您的命名空间(不要使用from testbase import *
或类似的):
import testbase
class TestMyClass1(testbase.TestBase):
values = ((1, 2), (3, 4))
class_under_test = MyClass1