python - 从父类继承单元测试

标签 python python-3.x unit-testing testing multiple-inheritance

我想以一种对所有从父类继承的类执行的方式编写一些测试。

例如,我有两个专业的电机类:

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/

相关文章:

python - 从每个列表中获取一个元素,列表的随机数

python - 如何在Python国际象棋中获得白棋的获胜机会

c# - 测试从另一个方法调用的方法

c# - 如何在 AutoFixture 中设置更复杂(类似 IoC)的注册

python - 高效的元组列表比较

python - Subprocess.popen - 从属写入失败 : Broken pipe; aborting

python - web2py中如何允许多个表单提交?

python - python init 函数中 master 和 master=none 的用途是什么?

python - 检查应用程序是否正在运行,而不是作为后台进程运行

.net - NSubstitute 是否支持 ref 参数?