扫码阅读
手机扫码阅读

聊聊单元测试的整洁

113 2024-01-31

这是鼎叔的第六十九篇原创文章。行业大牛和刚毕业的小白,都可以进来聊聊。

本文观点参考了Robert C.Martin,他是《代码整洁之道》的作者。‍‍‍

敏捷及TDD鼓舞了很多程序员编写自动化的单元测试(参考 聊聊测试驱动开发),但是他们经常会遗漏编写好测试时很重要的细节。测试代码也需要遵守一定的质量标准,“脏测试”等同于(甚至还不如)“没测试”。‍‍

测试代码和生产代码一样重要

测试代码更容易变成“极速增长的技术债务”,它必须随着生产代码的演进而修改,维护的代价也在上升,最终迫使技术经理放弃对测试代码的要求。再接下来就是代码的腐坏和团队对测试的失望。

正是单元测试让我们的代码可扩展、可维护和可复用,比生产代码更有利于项目的健康度,依托于这个防护网,程序员就不用担心对代码的修改,也不会失去改进代码结构的能力。因此测试代码理应被设计和被照料,就像生产代码一样整洁。‍‍‍‍‍‍‍‍

整洁的测试有什么特征

答案是可读性!这是最重要的特征,测试代码也要求是明确的,简洁的,拥有足够的表达力。‍‍‍

每个测试都应该清晰地被拆分为三个环节:构造测试数据,操作测试数据,检验是否得到预期的结果。读测试代码的人能够很快搞清楚意图,而不是深陷于细节。

更简洁有力的表现形式,还体现在开发人员对测试代码重构时,逐渐演变出一套测试API,包括包装这些API的函数和工具代码,这样写出来的测试,体现了面向特定领域的易读性。

从另一个方面看,测试代码毕竟是在测试环境而非生产环境运行的,这两个环境有本质不同。比如生产环境可能是嵌入式实时系统,它的CPU和内存资源非常有限,而测试环境则没有这个限制,因此有些测试在测试环境做没问题,但永远不会在生产环境做。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

单个测试中的断言应该最小化(最好只有一个),换一句话描述,就是每个测试函数只测试一个概念,我们不需要超长的测试函数。通过对测试概念的拆解,分为多个测试函数单独执行,这样更容易发现测试遗漏之处。‍‍‍‍‍‍‍‍

整洁测试的原则

做到测试的整洁,必须遵循这几个原则,这和之前分享的理念是相同的。

Fast 足够快速。运行缓慢的测试你就不会想频繁运行她,就无法轻易修正和清理代码。‍‍‍

Independent 独立的。每个测试不应为下一个测试设定条件,不应隐藏下级错误。‍‍

Repeatable 可重复的。如果测试不能在任意环境中重复,你就总会有个解释其失败的理由。‍‍

Self- Validating 自主验证。测试应该有一个是否通过的布尔输出,避免以来主观判断是否失败。‍‍‍‍‍‍

Timely 足够及时。单元测试应该恰好在使其通过的生产代码之前编写。‍‍‍‍

这些原则的首字母合起来就是 FIRST

复杂并发业务的低概率缺陷测试

在大量用户复杂业务中的代码,当有两个以上的线程使用同一个代码段和共享数据,可能因为并发进程以极低概率暴露严重缺陷。但是它们在普通自动化测试是难以发现的,更难以复现。

我们需要编写有潜力暴露问题的测试,在不同编程配置,系统配置和负载条件下频繁运行。

基于成熟的充分的持续测试建设,可以具备发现和修复这类问题的能力。思路如下:

1 如果测试失败就跟踪错误,别因为再次执行通过了就忽略失败,不要把系统错误归咎于“宇宙射线”这种偶发事件。

把伪失败看作可能的线程问题。并确保线程以外的代码可工作。

2 蒙特卡洛测试:测试脚本要灵活,随机改变调整值,多次运行,尽早运行。

允许线程依据吞吐量和系统使用率自我调整。

3 在每种可能的目标部署平台上重复运行测试。

编写可插拔,可调整的线程代码,让线程能在不同配置环境下运行。

4 模拟生产环境的负载后再测试。

运行多余处理器数量的线程,这样更有可能找到错过临界区或导致死锁的代码。

5 借助外部工具,通过装置试错代码的功能,强行改变代码的执行顺序,可以让非线性的安全代码以更高概率失效。比如生成一个随机数,让“Sleep,Yield和直接执行”这几种路径被自动随机选择。

比如IBM的ConTest这类工具,可以让千万次循环才能暴露一个错误的比率,提升到30次循环就能暴露错误。让编写良好的测试与“异动”组合,能有效增加发现错误的机会。

总结:测试的坏味道

1 测试不足。很多可能失败的计算和条件,还没有被探测到。

2 略过小测试。易于编写的小测试,在文档上的价值高于编写它的成本。

3 被忽略的测试。对不确定事物的疑问,背后涉及的代码没有被确定。

4 边界条件测试不够。算法的中间部分正确,但边界判断错误的情形,很常见。

5 缺陷集中的函数。缺陷往往扎堆在一起,当某个函数被发现一个缺陷,最好全面测试那个函数,你可能发现不止一个缺陷。

6 测试失败的模式。完整的测试用例,按合理的顺序排列,能暴露出特定的模式,从而得到解决问题的启发。

7 未被任何测试覆盖的代码。查看它,往往能发现失败的线索。

利用覆盖率工具可以汇报测试策略中的缺口。

8 慢速测试。时间一紧张,慢速测试就会被放弃,所以测试应当尽量快速。

代码坏味道给出的清单很难完美无缺,但确实给出了一套价值体系,而专业性和技艺来自这些驱动规矩的价值观。

原文链接: http://mp.weixin.qq.com/s?__biz=MzkzMzI3NDYzNw==&mid=2247484306&idx=1&sn=3e894ecdee46cd063fe5fe709ec40c79&chksm=c24fb6f0f5383fe6de52d66e83acd15c7a7a71a8cb5fa5a2dd61e5795f3e9b07e065f61ad32f#rd

《无测试组织-测试团队的敏捷转型》主题探讨。从打造测试的组织敏捷,到敏捷测试技术的丰富实践,从一线团队的视角来聊聊我们是怎么做的。面向未来,拥抱敏捷原则,走向高效能组织。

81 篇文章
浏览 14.9K
加入社区微信群
与行业大咖零距离交流学习
软件研发质量管理体系建设 白皮书上线