软体测试介绍 — 测试驱动开发 (TDD)

2024年10月17日

💎 加入 E+ 成長計畫 與超過 400+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

软体测试是每个软体工程师都需要掌握的技能,因此我们将陆续来谈这个主题,今天这期会先概要介绍软体测试的测试概览,大家常听到的测试金字塔 (Testing Pyramid) 与测试驱动开发 (TDD)。

什么是测试? 谁该写测试?

测试是软体品质与稳定性的把关,确保软体运行都符合需求,不会出现错误。测试的本质之一是找出错误,很多人可能会认为程式码审查(code review) 是在帮忙找错误,但先前微软的研究指出,程式码审查对协助找出错误的帮助有限。比起程式码审查(code review),测试更能协助找到错误,让软体上线前能把错误都排除,借此把关软体品质的存在。

在早期的软体开发模式中,开发者鲜少需要自己写测试,在那个年代,几乎都是由 QA 团队来负责测试的环节。然而,近年来软体业界的趋势有所改变,越来越多团队发现由开发者负责某部分的测试,对于整体效率、品质都会有所提升。

这与先前在《软体工程师该如何值班 (on-call)?》一文谈到的概念相似,当某个人需要为自己所做的结果负责时,做出的成果品质会比较高,因为如果品质不高,后果不再是由别人帮忙扛,而是自己得负责。

测试就是为软体的品质把关,所以当测试是由开发者负责,当程式出问题时,就不能甩锅说是 QA 没测到。当没办法甩锅,需要自己承担时,在写程式就会更加小心谨慎,以免未来的自己要帮现在的自己擦屁股。

虽说现在有不小部分的测试责任,是由开发者自己负责,有些团队仍会有自动化测试工程师,来协助涵盖更广的面向,包含非功能性 (non-functional) 的测试,例如效能、安全性、可用性等面向的测试,甚至是帮忙开发测试使用的模拟伺服器 (mock server)。

测试驱动开发 (Test-driven development)

当谈到软体测试,就不能不谈近年来社群中很常会听到的测试驱动开发 (Test-driven development,俗称 TDD)。

所谓的 TDD,是指在软体实际被开发前,就先写好测试。而这时候,因为还没有任何实际的程式码,所以测试都会跑不过;在有了测试后正式进入开发,然后一边开发一边通过不同的测试案例,等到所有测试案例都通过后,就算开发完成。

红灯-绿灯-重构 (Red-Green-Refactor)

当谈到 TDD,很常也会听到红灯-绿灯-重构 (Red-Green-Refactor) 这个流程。这个流程中有三个重要的元素,分别是:

  • 红灯:先写测试,但这时因为还没有实际的程式,所以程式码会跑失败。
  • 绿灯:接着写能通过测试的程式,这时先不追求程式码写多好,能过即可。
  • 重构:最初能通过测试的程式码,不必然是干净好维护的,这时要在能保持测试通过的前提下,重构程式码,让程式码变更干净好维护。
红灯-绿灯-重构
红灯-绿灯-重构

在这个概念下,很常被忽略的是重构这个步骤,很多人会觉得程式码都能通过测试就足够,但是如果没有去重构、确保程式码够好维护,也不能算真的照着 TDD 的精神在走。

这边的精神是指,TDD 是一种演进的角度看待程式码,从不能通过测试,到通过测试,再到高品质的程式码,逐步演进的精神。

是否该采用测试驱动开发?

社群对于 TDD 的采用与否,有很两极的观点,有人拥护,也有人认为不该使用。举例来说,史丹佛电脑科学系教授 John Ousterhout 曾说过自己是测试的拥护者,但是他不认为在软体开发时该用 TDD。

这是因为他认为,TDD 的做法过度关注在让功能可以如预期运行,而不是关注在探索最佳的软体设计方式。

从 TDD 的定义中可以看出,只要最终的功能可以通过所有预先写好的测试,那就算开发完成,即使后面有重构阶段,但这并没有去规范程式设计上该如何设计,而这正是 John Ousterhout 认为危险的地方。

此外,他认为 TDD 的出发点过于局限,因为每次关注的点,只在眼前需要通过的测试,而不是从更广的角度来看整体软体设计。而他认为,应该要从软体设计的角度出发,先把软体设计好后,再来写测试。

除此之外,假如是在原型开发阶段 (prototyping phase),因为功能面都还没确定下来,且产品与开发团队仍在探索,这时就相对不适合用 TDD。可以等到探索阶段结束后,进到稳定开发阶段,再选用 TDD。

不过 John Ousterhout 同时表示,有些情况下 TDD 确实会很有用。具体来说,他认为在修正错误 (bug fixing) 时,用 TDD 是不错的选择。当程式有错误 (bug) 时,就会如 TDD 最开始测试无法通过的状态;这时先把测试写好,等同于是在规范程式预期会有什么样的行为,而为有在通过这些测试后,才能确保错误被修正。可以看到在这种状况下,TDD 的做法就非常合适。

阅读更多

如果你对于「软体测试」这主题感兴趣,我们在 E+ 有写更深入详细的内容,包含测试金字塔 (Testing Pyramid)、测试金杯 (Testing Trophy) 等主题。有兴趣的读者,欢迎加入 E+ 成长计划。

本文为 E+ 成长计划的深度内容,截取前三分之一开放免费阅读。欢迎加入 E+ 成长计划阅读完整版本 (点此了解 E+ 的详细介绍)

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們