我正在为一位同事审核一些代码,并在单元测试类中看到了这样的测试:
// 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%)的目标实现100%覆盖?
谢谢。
EDIT / UPDATE:
这不是关于如何正确测试被测系统的问题(我知道这不是单元测试的原因,我知道如何正确地将其转换为单元测试),也不是一个问题关于FooToBarConverter的报道。我希望对被测系统的代码覆盖率有所了解:对被测系统的集成测试是否足够?还是应该进行单元测试?
答案 0 :(得分:5)
我认为这里的答案是“它取决于”。
如果您在FooToBarConverter
课程上有完整的单元测试覆盖率,那么您可能只需使用systemUnderTest
的集成测试即可,因为您可以放心地说明真实FooToBarConverter
在此上下文中表现出预期的行为,因此不会错误地影响测试结果。
另一方面,目前尚不清楚该测试的具体内容 - 您是否在systemUnderTest
内检查FooToBarConverter
的行为,或systemUnderTest
内的其他预期副作用? {1}} FooToBarConverter
纯粹是巧合的演员?{1}} (即你确定这不是bar
的间接测试吗?)
现在个人我建议您也为FooToBarConverter
进行正确的“纯”单元测试(使用systemUnderTest
的模拟或存根),因为
它会使回归更容易管理;假设将来某些更改FooToBarConverter
使其单元测试失败 - 它们很可能因此也会使此集成测试失败。对于那些查看失败测试并且不知道可以忽略集成测试失败并且只需要修复FooToBarConverter测试的人来说,这可能会令人困惑。我知道,这是一件小事,但有一天可能会节省5分钟的重要时间:)
如何测试否定案例(给定已损坏/无效/ systemUnderTest
时FooToBarConverter
的行为?既然你可能不得不为这种情况编写带有存根/模拟的单元测试,你也可以在同一个项目/测试类中对好的情况进行单元测试,它更清晰 - 否则你有聚合单元测试和集成测试项目中的代码覆盖率,以验证systemUnderTest
是否完全覆盖......
另外,不要担心100%的代码覆盖率;这很好,但在实践中很少见到它。我并不是说这对于良好的设计实践来说也是如此;简单的现实是,没有任何设计是100%完美的,因此可以预期有时候你没有时间/资源/意愿来重构你的类以允许每个单独的依赖注入,或者是能够为每个缝间交互等使用接口
希望有所帮助。