【发布时间】:2013-03-15 20:02:55
【问题描述】:
在我的办公室,除了对主要负责与文件系统(DB 等)交互的类进行集成测试外,我们对单元测试的必要性存在争议。
我们拥有的集成测试几乎是单元测试,因为测试对象根本不与其他对象交互。我们将测试称为 integration 的唯一原因是在测试中使用了真正的文件系统。并且建议让被测类使用文件系统层组件,然后在测试中模拟它(所以我们将它们称为unit测试),并检查与该组件的交互,而不是真实的文件系统结果。我们讨论的是这种改变的必要性。
我们的一个观点是,单元测试总是需要的,因为:
- 编写单元测试让代码变得更好
- 拥有单元测试,您无需关心真实的文件系统和文件的副作用,出现在错误的位置
- 开发人员可以通过使测试的类使用文件系统模拟并为该模拟设置适当的期望来全面测试结果
- 可以将模拟期望与测试类的特定内部算法联系起来,因为我们使用单元测试进行白盒测试
因此,必须始终为这样的测试类编写单元测试。并且该类必须始终使用文件系统层组件进行测试。
另一种观点是,专门用于文件系统交互的类的特定边缘情况不需要单元测试,因为:
- 仅通过简单的模拟而不是真实的文件系统(或其完整仿真),无法正确验证测试类是否有效。文件系统是一个如此复杂的组件,它:
- 经过测试的课程可以以多种不同的方式工作,以获得成功的结果。模拟期望仅涵盖一两种可能的场景,因此单元测试错误地显示正确实现良好算法的类的失败,这与预期不同。
- 经过测试的类可以以某种方式工作,被模拟检测为成功的场景,但该类仍然没有产生正确的结果。这可能是由于实际文件系统中相当复杂的原因。所有这些原因是不可能仅仅通过一个模拟来涵盖的。
- 带有模拟和期望的单元测试非常脆弱,因为它与测试类的内部算法密切相关。并且即使对算法进行正确的更改,测试也会错误地失败。
- 当类只有 1-2 个公共方法,并且唯一的依赖项是文件系统时,集成测试是单元测试的正确和完全替代。集成测试在这种情况下提供与单元测试相同的好处 - 清晰的依赖关系,更易读的代码等。
因此,在我们的案例中不需要使用文件系统模拟进行单元测试。对于这种特殊的类情况,它很脆弱并且不准确。
所以,总而言之,问题是:
对于没有复杂类的边缘情况,集成测试是否足够充分,它主要负责使用文件系统(数据库等)?
这个类的 integration 和 unit 测试之间的唯一区别是,对于单元测试,将使用文件系统模拟(类将被完全隔离),而对于集成测试使用的真实文件系统。
如果您可以添加对经典书籍的引用,或者可能是知名业内人士的文章/演示文稿,我将不胜感激,这样我们就可以有一个非常强大的基础来支持得出的结论。
【问题讨论】:
-
growing-object-oriented-software.com 这是我参考的 TDD 书籍之一,也许这会有所帮助。顺便说一句,单元测试不需要测试每个分支,而是专注于测试行为。
-
stackoverflow.com/questions/129036/… 这是与此类似的关于 SO 的问题之一。
-
谢谢你,@NarendraPathai。我看过那张票,但我也在寻找一些对普遍采用的来源(书籍、文章等)的参考。
标签: unit-testing mocking integration-testing