前言
近期我对自己看待编写程序这件事有更高的期许,除了最基本的性能、可读性、扩展性……还有一个非常重要的领域就是:测试。
不过程序好端端的能动就代表测试没有必要了吗?在我刚工作时实际上做了一段时间的自动化 QA 工程,不过那时候的我其实也并不明白写测试的原因,就是有程序就拿来自动化测试,并没有想太多。
这篇就是适合写给没有测试经验想入门的人,目标对象差不多就是我先前的自己。
为什么要测试?如何发挥测试的价值?
写测试是一件好事对吧?可以自动的验证程序的行为,确保程序的正确性,这样就不用每次都要手动测试了,可以通过自动化来节省手动测试。
这是我最初的想法,然后就一头栽进去写很多测试,花大把的时间替每个功能都加上测试,然后发现……没发挥什么作用。
一、测试只在被执行时才有价值
一个程序的价值体现在它被执行使用的时候,而一段测试的价值也体现在它验证了程序的某个行为的正确性;就算程序架构得再烂但因为可以运作所以持续的产出价值,同理一段测试再完美但因为没有验证到任何行为所以是没有价值的。
我犯下最大的错就是单纯写了很多测试但没有积极的去执行,让测试尽量跑起来,验证程序的行为就是测试的价值所在,成功的测试带给你信心,错误的测试替你抓 BUG。
这里的信心是指确定程序如预期般的行动,你会更有自信的去架构代码并确保改动不会对被验证过的行为造成影响。将测试导入开发流程的重要性不亚于测试本身,不会动的测试就是单纯的案例文件,有人没事会去看不常用且没有约束力的规格文件吗?没有!
二、测试即文件
前面提到测试其实就像是规格书,试想看看一份详尽的规格文件,通过一些魔法可以让这份文件可以随时随地自动化验证程序的行为,提醒开发者哪里不符合预期……这不就是测试吗?
测试本质上就是一种自动化规格书。开发与测试并不是两个世界而是相辅相成的关系,反复的「事先」写下对程序的期望测试并实践,一直重复这样的流程你就发现了 TDD (Test Driven Design)测试驱动开发!这种做法就不会让测试与规格脱节,因为测试就是规格。
但在这里仍然是工程师写下自己的期望并反复迭代出可以被自动化验证正确性的程序,商业人士也有他们自己的规格书要写,把大家的文件整合为一种依照行为而不是实现细节为主的规格书,并在根据演进为其加上测试、实现细节,这就是 BDD (Behavior Driven Design)行为驱动开发。
「测试即文件」的意思是希望换一个思维去接受测试,不要把测试当成是一种负担,而是在开发层面上了解实现是「结果」但在这之前「原因」也同样重要。
三、撰写测试是为了更高的效率
节省时间: 有些种类问题测试起来费时费力,可能会需要刁钻的模拟用户进行特定的操作或权限、等待画面读取、验证画面元素、验证各式各样种类的状态……会需要大量人工时间的,或是很难通过人工来达成,算下来自动化测试就是值得的投资。
降低风险: 或是说有时候程序重要到一丁点错误都不能犯下(金钱交易、性命攸关),那么测试也可以帮助你确保程序的正确性,算下来减缓开发速度确保每件事都正确运作也是值得的。
总结
测试是个充满争议的话题,灵活性与正确性你选谁?是先有良好的规格再实现,还是先实现再补上规格?这是一个永远存在的问题。有人宁愿牺牲静态检查、也有人认为测试是必要严格且优先于实践。背后其实已经不只是技术,而是整个团队文化、产品要考虑的问题。
我可以确定一件事:没被测试的程序不是非常简单需要快速迭代(尚不清楚价值),就是变成没人晓得如何运作的意大利面(有价值但你害怕改动),这两点的平衡也是艺术。
遗留代码(Legacy Code)是指害怕更改的有价值的代码