Q: 需求变了怎么办? 岂不是有大量测试用例需要修改?
A: 难道不是应该的吗? 难道以前的需求文档在需求发生变化时不需要修改? 哦, 或许它们不需要, 因为没人会关心, 对代码也没什么影响, 需求文档在度过最初的几周后便被扔在配置库里再也没人管它了.
Q: 我的单元测试编译链接速度很慢, 而且有些条件很难测, 比如内存不足, 或者环境很难搭建, 比如需要网络或数据库, 怎么解决?
A: 这是集成测试, 不是单元测试. 你一定把系统所有的组件都编译链接起来了. 那么如果你的测试失败了, 是哪一部分的问题呢?
通常单元测试需要满足一个条件: 不依赖任何其它单元, 即隔离性. 实现手段就是在测试环境中能够轻易的假冒依赖, 并设定依赖按照我们的意愿进行工作. 一个例子就是你的代码依赖 malloc 获取内存, 而你想测试内存不足的情况. 那么我们应在能够/需要在单元测试中使用使用一个假冒的 malloc 来代替真正的 malloc, 并且我们能控制假冒的 malloc 返回 NULL 以模拟内存不足的情况. 关于如何做到这一点, 可参考一些成熟的"假冒"框架, 如 mockcpp 等.
Q: 我原来的测试都是用真实的代码来跑, 一个测试能覆盖多个单元. 你现在都把依赖替换掉了, 那被替换掉的模块有问题怎么办? 怎么保证集成真实的代码后还能正确工作?
A: 其它单元有其它单元自己的单元测试, 各自关注自己. 集成测试像以前一样, 该怎么测还怎么测, 并不是有了单元测试就不要其它测试了.
Q: 单元测试就是设计? 单元测试怎么能反映/代替设计 ?
A: 单元测试反映的是局部的设计, 局限于本单元以及与之交互的其它单元. 前面说的单元测试能够反映系统的其它部分对当前单元的需求, 所谓设计就是单元之间的职责划分, 交互和依赖关系
当你试图测试一个单元时, 却发现需要创建大量的其它对象, 而且按照你脑海中的实现, 有些对象是在单元内部创建的, 根本无法在测试环境中假冒它们. 这时候, 你即使只是为了减少测试的难度, 也会逼迫自己思考:
-
这个单元是否做了太多的事, 承担了额外的职责, 违反了单一职责原则?
-
是否应该把依赖让外界设置进来, 而不是自己在内部创建, 这样测试时就能把依赖设置为假冒的实现?
是的, 单元测试警示你思考一下自己的设计
Q: 单元测试是设计, 还有人说源代码是设计, 到底是测试是设计还是源代码是设计?
A: 这实际上是另外一种角度. 源代码就是设计的论断基于两个假设
如果我们认同这两个假设, 那么软件工程师的什么产物能够被严格并且重复实现的呢? 是你的Word形式的"设计"文档吗? 是CAD工具画出的UML图吗? 都不是, 因为它们都不精确, 有无数种实现方式, 根本谈不到严格, 不同的开发人员会有完全不同的实现. 事实上, 只有源代码,才能满足这个约束. 这样软件的设计阶段, 就是直到软件工程师完成源代码的那一刻, 而软件的实施阶段, 其实就只剩编译和部署了. 跑题了.
文章来源于领测软件测试网 https://www.ltesting.net/