我想以一种对所有从父类继承的类执行的方式编写一些测试。
例如,我有两个专业的电机类:
class Motor():
def run(self, energy):
pass
class ElectricMotor(Motor):
def run(self, electric_energy):
heat = electric_energy * 0.99
motion = electric_energy * 0.01
return heat, motion
class DieselMotor(Motor):
def run(self, diesel_energy):
heat = diesel_energy * 0.65
motion = diesel_energy * 0.35
return heat, motion
然后我有两个适用于每种电机的测试:
class MotorTest(unittest.TestCase):
def test_energy_should_be_conserved():
for class_instance in all_motor_child_classes:
energy=10
assert sum(class_instance.run(energy))==energy
energy=20
assert sum(class_instance.run(energy))==energy
def test_motors_should_produce_heat():
for class_instance in all_motor_child_classes:
energy = 10
heat, motion=class_instance.run(energy)
assert heat>0
我正在寻找的是一种执行循环的方法
for class_instance in all_motor_child_classes:
或不同的编程模式以获得相同的结果。
有什么想法吗? 谢谢 里卡多
最佳答案
嗯,这里有两点:首先有一个 Motor
子类的列表,然后有每个类的实例。
愚蠢的简单解决方案是在测试用例的 setUp
中维护这些列表:
from motors import ElectricMotor, DieselMotor
class MotorTest(unittest.TestCase):
_MOTOR_CHILD_CLASSES = [ElectricMotor, DieselMotor]
def setUp(self):
self.motor_child_instances = [cls() for cls in self._MOTOR_CHILD_CLASSES]
def test_energy_should_be_conserved():
for class_instance in self.motor_child_instances:
self.assertEqual(sum(class_instance.run(10)), 10)
# etc
如果您的 Motor
子类 __init__()
期望不同的参数(如果您想要 proper subtyping according to liskov substitution principle,它们不应该这样 - 但是,好吧,“实用胜于纯粹” ),您可以将这些参数添加到您的 MOTOR_CHILD_CLASSES
列表中:
# (cls, args, kw) tuples
_MOTOR_CHILD_CLASSES = [
(ElectricMotor, (42,), {"battery":"ioncad"}),
(DieselMotor, (), {"cylinders":6}),
]
并在 setUp()
中使用它们:
self.motor_child_instances = [
cls(*args, **kw) for cls, args, kw in self._MOTOR_CHILD_CLASSES
]
对于更“自动”的东西,您可以在 Motor
上使用自定义元类,这样它就可以注册其子类并提供它们的列表,但是这样您将失去提供 per- 的能力类参数 - 您还将使测试代码的可读性和可预测性大大降低。
现在另一种 - 恕我直言 很多 更好的方法是在你的测试中使用继承:定义一个 mixin 对象,其中包含所有 Motor
child 共有的所有测试类(class):
class MotorTestMixin(object):
# must be combined with a unittest.TestCase that
# defines `self.instance` as a `Motor` subclass instance
def test_energy_should_be_conserved(self):
self.assertEqual(sum(self.instance.run(10)), 10)
def test_should_produce_heat(self):
heat, motion = self.instance.run(10)
self.assertGreater(heat, 0)
然后每个子类有一个 TestCase:
class DieselMotorTest(MotorTestMixin, TestCase):
def setUp(self):
self.instance = DieselMotor()
class ElectricMotorTest(MotorTestMixin, TestCase):
def setUp(self):
self.instance = ElectricMotor()
这种方法的好处之一(其他是简单性、可读性和更好的失败测试错误报告 - 您将立即知道哪个子类失败而无需执行任何特殊操作)是您不需要在添加新的 Motor
子类时触及现有代码 - 您只需要为其添加一个新的单独的 TestCase -,您甚至可以在一个不同的模块中这样做,遵循 open/closed principle .
关于python - 从父类继承单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54073241/