使c ++代码易于测试的模式

Joa*_*son 11 c++ testing dependency-injection testability

您是否应该设计代码以使测试更容易?如果是这样的话,如何设计c ++代码以便于测试.

  • 你如何在c ++中应用依赖注入?
  • 我应该使用纯接口类作为基础来实现类,以简化伪测试对象的创建?
    • 这会迫使我制作很多虚拟方法.这会影响性能吗?
  • 在c ++中设计可测试性时我还应该考虑什么?

jal*_*alf 9

我应该使用纯接口类作为基础来实现类,以简化伪测试对象的创建?

  • 这会迫使我制作很多虚拟方法.这会影响性能吗?

我经常使用的一种解决方法是对类进行模板化,而不是将其隐藏在接口后面.然后我可以在测试时传递测试/模拟对象作为模板参数,否则传递真实对象.这样,避免了虚拟功能的性能损失.

编辑
确定,一个简单的例子:

使用OOP和接口,您可以编写如下函数:

void Foo(IBar& someBar) { ... }
Run Code Online (Sandbox Code Playgroud)

此函数接受一个实现IBar接口的参数,并对其执行某些操作.如果你想传入一个虚拟模拟实现,你只需编写一个继承自IBar并传递给它的模拟对象Foo.简单明了.

但是您可以使用模板实现相同的功能:

template <typename BarType>
void Foo(BarType& someBar) { ... }
Run Code Online (Sandbox Code Playgroud)

......就是这样.身体Foo可以保持不变.只要传递给函数的类型公开我们需要的所有成员,它就可以工作,而不必正式继承接口类,并且没有虚函数和运行时多态的开销.

  • 当然,模板可能会使编译时依赖性变得更难,因为它们的实现进入了头部. (3认同)
  • @Matthieu M:实现可能不必进入标题.请记住,实际的生产代码只会使用一组类型(真实的,非模拟的,非测试的)来实例化模板.因此,定义可能只需要在一个翻译单元中可见.然后你的测试可能直接包括.cpp.您的测试代码可能会因此而变得有些狡猾,但这可能是值得的权衡 - 单元测试不一定是超级优雅的代码. (2认同)

Dmi*_*try 5

从一开始就不要设计太多,然后编写测试,然后使其通过,但不要超过此数量。保持你的功能非常短。查看您已完成的工作并进行重构。如果要编写注释,最好将有问题的代码放在一个单独的函数中,并使用好名字。

而且不要花太多时间思考模式,这是很多科学知识,几乎没有结果,只需先编写测试并保持代码简单即可,然后,令人惊讶的是,您无需为此编写测试,就可以了它已经。和您的代码工作。