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


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

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

12732
2017-11-05 14:39


起源

设计可测试性确实是必须的。然而,您还必须意识到只有“边界”应该以独立方式进行测试,内部组件相互依赖并且不能单独测试是完全合理的。 - Matthieu M.
你可能对此感兴趣 堆栈交换提案。它几乎准备好开始测试,只需要更多。 - greatwolf


答案:


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

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

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

编辑
好的,一个简单的例子:

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

void Foo(IBar& someBar) { ... }

该函数采用实现的参数 IBar 接口,并用它做一些事情。如果你想传入一个虚拟模拟实现,你只需编写一个继承自的模拟对象 IBar 并传递给 Foo。简单明了。

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

template <typename BarType>
void Foo(BarType& someBar) { ... }

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


9
2017-11-05 15:04



我在哪里可以阅读有关如何模板化课程的更多信息?有描述这种情况的模式吗? - Joakim Karlsson
为什么你想要一切模式? jalf向您展示了单独保留继承(虚拟/多态)并使用C ++模板(通用编程)的想法。给予通用模拟(模板代码)将涵盖您将使用的“所有”可能类型(使用一个函数,而不是许多“虚拟方法”)。 - bua
当然,模板可能会使编译时依赖性变得更难,因为它们的实现进入了头部。 - Matthieu M.
不,我不是说我需要一个模式。我只是想看看他的意思。我不明白jalf在答案中的含义是什么意思。 - Joakim Karlsson
@Matthieu M:实现可能不必进入标题。请记住,实际的生产代码只会使用一组类型(真实的,非模拟的,非测试的)来实例化模板。因此,定义可能只需要在一个翻译单元中可见。然后你的测试可能直接包括.cpp。您的测试代码可能会因此而变得有些狡猾,但这可能是值得的权衡 - 单元测试不一定是超级优雅的代码。 - jalf


不要设计 太多了 从一开始,然后写一个测试,然后让它通过,但不是更多。保持你的功能 非常 短。看看你做了什么 重构 它。如果您要撰写评论,最好将有问题的代码放到具有良好名称的单独函数中。

并且不要花太多时间思考模式,这是很多科学和结果很少,只需先编写测试并保持代码简单,然后,令人惊讶的是你不需要为它编写测试,你已经完成了它已经。你的代码有效。


4
2017-11-05 17:09



“如果你要撰写评论,最好将有问题的代码放到一个名字好的单独函数中”这是非常好的建议。 - Steven Keith


最大 凝聚 最小化 耦合

通过测试,这将使您的生活更轻松。


3
2017-11-05 14:47





我认为首要关注的是......

  1. 实现功能
  2. 代码可扩展性
  3. 代码可恢复性
  4. 代码可维护性

0
2017-11-05 15:04