![](/img/trans.png)
[英]Optimization and testability at the same time - how to break up code into smaller units
[英]How do I factor code to ease testability?
我正在学习单元测试,并想知道如何编写可测试的代码。 但是,我不确定如何在不使其复杂的情况下编写可测试代码。 我将采用着名的汽车和发动机问题来描述问题。
class Car
{
private:
Engine m_engine;
public:
Car();
// Rest of the car
}
我提出了以下解决方案,以使上述代码可测试。
更改Car的构造函数以将Engine作为参数。 然后模拟引擎并进行测试。 但是,如果我没有不同类型的引擎,那么参数化构造函数似乎是不合适的,只是为了使它可测试。
使用setter然后将模拟引擎传递给setter。 与上述相同的流程。
首先测试引擎,然后使用经过验证的引擎(或使用存根引擎)测试汽车。
我必须在代码上测试哪些替代方案? 每种方法的优点和缺点是什么?
从不同的(测试驱动开发)观点来看:易于测试的代码易于使用。 编写单元测试实际上是在测试代码的“公共接口”。 如果它很难测试,那是因为你在那里有一些依赖,这使得它很难。 你真的需要一个遏制关系,还是一个联想关系会更有意义?
在你的情况下,我个人认为在构造函数中传递Engine会更容易测试,所以我会像你的建议#1那样重构构造函数。 您可以在一个测试套件中测试引擎,并提供一个模拟引擎来测试另一个测试套件中的Car。 现在测试它很简单,这意味着界面易于使用。 这是好事。
现在考虑如何在实际项目中使用该实现。 您将创建一个CarFactory类,工厂将创建一个引擎并将其放入Car中,然后再将其交付给您。 (还要注意这最终如何更接近地模拟汽车,发动机和工厂的真实世界,但我离题了。)
因此,TDD的答案是重构代码以在构造函数上获取Engine指针。
如果您只有一个引擎类型,为什么要尝试将其作为新对象? 如果您不打算交换引擎,请不要创建另一个抽象层。 只需将发动机作为汽车的一部分。
您可能正在分解以降低复杂性,而不是重用组件。 好决定。 在这种情况下,我会说3是你最好的选择 - 验证你的低级组件,然后使用调用较低级别对象的更高级代码。
实际上,Engine更像是数据库。 并且您将需要更改构造函数以使用不同的数据库(出于测试原因或其他原因),但您可以暂时搁置该谎言。
正如其名称所暗示的,单元测试是关于测试单元以确认它们按照规定工作。 这意味着,您应该单独测试引擎。
系统测试或集成测试是关于测试它们是否正确“粘合”在一起。
当然,它比这更复杂,但它应该指向正确的方向。
选项1通常是正确的方式。
通过完全控制您给汽车的发动机,您可以很好地测试汽车。
您可以使用引擎为汽车提供的所有不同输出,更轻松地测试汽车的行为方式。 您还可以确保汽车对发动机进行适当的调用。
在构造函数中使用它可以清楚地表明Car依赖于引擎来工作。 将它与依赖注入框架一起使用,构造函数问题根本不是问题。
真正的问题是,有哪些要求? 如果目标是简单地实现“汽车”对象,那么它甚至不需要引擎。
测试应始终与要求相关。 任何对象模型都将是对现实的一些概括,因此问题在于需要表示哪些方面。
一旦你的需求下降,那么你应该在通用的高级别上编写测试。 然后,OO设计应该以这样的方式完成,即可以实现这些测试。
C ++的一个可能性是使用友谊:
class Car
{
private: //for unit testing
friend class TestCar; //this class is the unit test suite for the Car class
Car(Engine* mockEngine); //this constructor is only used by the TestCar class
private:
Engine* m_engine;
public:
Car();
// Rest of the car
};
第二种可能性是构造函数的实现使用全局/静态方法,例如如下所示,您可以通过一些配置文件或通过链接(可能是动态链接)到此不同版本来更改此方法的实现方法:
Car::Car()
{
m_engine = Engine::create();
}
我主张允许(通过构造函数或属性)将Engine的实现添加到Car(最好是IEngine)。
汽车测试实际上并不关心引擎的作用,只要它能够正确响应调用引擎的结果。 然后,使用假引擎进行测试,以便您可以控制发送到汽车的信号,您应该好好去。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.