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% 的覆盖率(或者甚至完全达到 100% 的目标)?

谢谢你。

编辑/更新:

这不是关于如何正确地对被测系统进行单元测试的问题(我知道这不是单元测试的原因,并且我知道如何正确地将其转换为单元测试),也不是关于覆盖率的问题FooToBar 转换器。我想对被测系统的代码覆盖率提出意见:对被测系统的集成测试是否足够?还是应该有单元测试?

4

1 回答 1

6

我认为这里的答案是“视情况而定”。

  • 如果你对FooToBarConverter类有完整的单元测试覆盖率,那么你可能只需要集成测试就可以了,systemUnderTest因为你可以自信地说,FooToBarConverter在这种情况下,真实的行为符合预期,因此不会错误地影响测试结果。

  • 另一方面,目前还不清楚这个测试具体检查的是什么——你是在检查systemUnderTest当给定一个 valid 时的行为FooToBarConverter,还是其他一些预期的副作用systemUnderTest,其中FooToBarConverter纯粹是巧合的演员?(即您确定这不是对 的间接测试bar吗?)

现在,我个人建议您也进行适当的“纯”单元测试(使用 的模拟或存根FooToBarConverter),systemUnderTest因为

  • 这将使回归更容易管理;假设将来某些更改FooToBarConverter会使其单元测试失败 - 他们很可能也会因此使此集成测试失败。对于查看失败测试并且不知道可以忽略集成测试失败并且只需要修复 FooToBarConverter 测试的人来说,这可能会令人困惑。这是一件小事,我知道,但有一天它可能会节省 5 分钟的重要时间 :)

  • 您如何测试负面案例(systemUnderTest给出损坏/无效/空时的行为FooToBarConverter)?因为无论如何你可能不得不为这些案例编写带有存根/模拟的单元测试,所以你也可以在同一个项目/测试类中对好的案例进行单元测试,这样会更清楚 - 否则你有汇总单元测试和集成测试项目的代码覆盖率,以验证systemUnderTest是否完全覆盖......

另外,不用担心 100% 的代码覆盖率;拥有它很好,但在实践中很少看到它。我也不是说这是对良好设计实践的一种安慰。简单的现实是,没有任何设计是 100% 完美的,因此可以预料,有时您只是没有时间/资源/意愿重构您的类以允许注入每个依赖项,或成为能够为每个接缝间交互等使用接口。

希望有帮助。

于 2013-11-01T10:12:56.527 回答