集成测试、单元测试和代码覆盖率

7

我正在为同事审核一些代码,发现测试单元类中有一个测试看起来像这样:

// setup
Foo f = ...
FooToBarConverter ftb = ...
Bar b = ftb.Convert(f); // It is easier to create a Bar by converting it from a Foo than making one 'from scratch'

// test
systemUnderTest.DoSomething(bar);

// assert
Assert.IsTrue(...)

显然,这是一个集成测试,因为它测试了FooToBarConverter以及系统下的测试,因为它是唯一覆盖DoSomething()方法的测试。我建议将此测试移动到集成测试解决方案,但这会降低单元测试的代码覆盖率。我们的目标是实现100%的单元测试代码覆盖率(是的-我知道100%覆盖率是手段而不是目的本身,100%覆盖的代码不一定是100%正确的代码)。
如果我们将集成测试移到外面,是否有理由创建单元测试来恢复覆盖率?
或者,我们的目标是错误的,应该针对所有测试组合实现100%覆盖率(甚至追求100%覆盖率)?
谢谢。
编辑/更新:
这不是关于如何适当地对系统进行单元测试的问题(我知道这不是单元测试的原因,我知道如何将其正确转换为单元测试),也不是关于FooToBarConverter覆盖范围的问题。我想听听关于系统下测试的代码覆盖率的意见:系统下的集成测试是否足够?还应该进行单元测试吗?
1个回答

6
我认为答案是“这取决于情况”。如果您的FooToBarConverter类具有完整的单元测试覆盖率,那么只进行systemUnderTest的集成测试可能就足够了。因为在这种情况下,您可以自信地说实际的FooToBarConverter在该上下文中表现符合预期,因此不会错误地影响测试结果。
另一方面,不清楚这个测试具体检查什么内容-您是要检查给定有效的FooToBarConvertersystemUnderTest的行为,还是要检查在systemUnderTest内部产生的某些其他预期副作用,而FooToBarConverter只是一个纯粹偶然的参与者?(即您确定这不是对bar的间接测试吗?)
现在,就我个人而言,我建议您也对systemUnderTest进行适当的“纯”单元测试(使用FooToBarConverter的模拟或存根),因为:
它将使回归更容易管理;假设将来对FooToBarConverter进行某些更改导致其单元测试失败-很可能也会导致此集成测试失败。这可能会让查看失败测试的人感到困惑,并且不知道可以忽略集成测试失败,只需修复FooToBarConverter测试即可。我知道这是小事,但有时可能会节省5分钟的重要时间:)
您如何测试负面情况(给定损坏/无效/空值的FooToBarConvertersystemUnderTest的行为)?既然您可能必须编写带存根/模拟的单元测试来处理此类情况,那么最好在同一项目/测试类中为良好的情况编写单元测试,这更清晰-否则,您必须聚合跨两个单元测试和集成测试项目的代码覆盖率,以验证systemUnderTest已完全覆盖...
另外,不要担心100%的代码覆盖率;拥有它很好,但实际上很少见。我并不是说这是对良好设计实践的安慰;简单的现实是没有设计是100%完美的,因此可以预期有时您没有时间/资源/意愿来重构类以允许注入每个依赖项,或者能够为每个交互接缝使用接口等。
希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接