gpt4 book ai didi

python - 如何在 python 中对工厂进行单元测试?

转载 作者:太空狗 更新时间:2023-10-30 02:12:58 24 4
gpt4 key购买 nike

当进行单元测试时,class one 应该只针对其协作者的公共(public)接口(interface)进行测试。在大多数情况下,这很容易实现,用假对象 - Mocks 替换协作者。如果正确使用依赖注入(inject),大多数情况下这应该很容易。

但是,当尝试测试工厂类时,事情会变得复杂。让我们看例子

模块 wheel

class Wheel:
"""Cars wheel"""

def __init__(self, radius):
"""Create wheel with given radius"""

self._radius = radius #This is private property

模块 engine

 class Engine:
"""Cars engine"""

def __init(self, power):
"""Create engine with power in kWh"""

self._power = power #This is private property

模块 car

class Car:
"""Car with four wheels and one engine"""

def __init__(self, engine, wheels):
"""Create car with given engine and list of wheels"""

self._engine = engine
self._wheels = wheels

现在让我们有CarFactory

from wheel import Wheel
from engine import Engine
from car import Car

class CarFactory:
"""Factory that creates wheels, engine and put them into car"""

def create_car():
"""Creates new car"""

wheels = [Wheel(50), Wheel(50), Wheel(60), Wheel(60)]
engine = Engine(500)
return Car(engine, wheels)

现在我想为 CarFactory 编写单元测试.我想测试一下,工厂是否正确地创建了对象。但是,我不应该测试对象的私有(private)属性,因为它们将来可能会被更改,这会破坏我的测试。想象一下,Wheel._radius替换为 Wheel._diameterEngine._power替换为 Engine._horsepower .

那么如何测试工厂呢?

最佳答案

幸运的是,由于 monkey_patching,在 Python 中测试工厂很容易。您不仅可以替换对象的实例,还可以替换整个类。让我们看例子

import unittest
import carfactory
from mock import Mock

def constructorMock(name):
"""Create fake constructor that returns Mock object when invoked"""
instance = Mock()
instance._name_of_parent_class = name
constructor = Mock(return_value=instance)
return constructor

class CarFactoryTest(unittest.TestCase):

def setUp():
"""Replace classes Wheel, Engine and Car with mock objects"""

carfactory.Wheel = constructorMock("Wheel")
carfactory.Engine = constructorMock("Engine")
carfactory.Car = constructorMock("Car")

def test_factory_creates_car():
"""Create car and check it has correct properties"""

factory = carfactory.CarFactory()
car_created = factory.create_car()

# Check the wheels are created with correct radii
carfactory.Wheel.assert_called_with(radius=50)
carfactory.Wheel.assert_called_with(radius=50)
carfactory.Wheel.assert_called_with(radius=60)
carfactory.Wheel.assert_called_with(radius=60)

# Check the engine is created with correct power
carfactory.Engine.assert_called_once_with(power=500)

# Check the car is created with correct engine and wheels
wheel = carfactory.Wheel.return_value
engine = carfactory.Engine.return_value
carfactory.Car.assert_called_once_with(engine, [wheel, wheel, wheel, wheel])

# Check the returned value is the car created
self.assertEqual(car_created._name_of_parent_class, "Car")

所以我们用 Mock 替换类及其构造函数,它返回我们的假实例。这使我们能够检查,构造函数是使用正确的参数调用的,因此我们不需要依赖真实的类。我们真的可以在 python 中不仅使用假实例,还可以使用假类。

此外,我不得不提一下,上面的代码并不理想。例如,假的构造函数应该为每个请求真正创建新的 Mock,这样我们就可以检查汽车是否用正确的轮子调用(例如正确的顺序)。这可以做到,但代码会更长,我希望示例尽可能简单。

在示例中,我使用了 python 的 Mock 库 http://www.voidspace.org.uk/python/mock/

但这不是必须的。

关于python - 如何在 python 中对工厂进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12237454/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com