- 原文地址:Unit testing, Lean Startup, and everything in-between
- 原文作者:Itamar Turner-Trauring
- 译文出自:掘金翻译计划
- 译者:gy134340
- 校对者:zhaochuanxing,yifili09
为什么软件需要测试?
我曾经以为是为了产出高质量的代码:你总是需要测试因为你总是需要写出高质量的代码。
但是这个观点有几点问题。
有时候质量不是主要问题。
在“精益创业” 这本书中,作者 Rric Ries 说过有时候发布一个软件最终发现没人真的想用它。
这也是他创作的动机之一: 为创业初期建立一套更好的方法论,在真正投入时间去构建一个高质量的产品时,就能够发现这款产品是否能够成功的方法论。
如果没人用你的软件的话那么确保高质量纯属浪费时间。
即使高质量很有必要,但高质量与测试之间的关系却很模糊的。
一个 QA 的团队跟自动化的单元测试又什么不同?
他们的确不一样,但他们又分别给出什么样的质量?
什么时候需要特别的测试?
另外,测试是有成本的:你怎样辨别成本的花费是否超出回报?
比如说,有一家做税务申报软件的公司(我稍微改了一下细节)。
他们使用 Selenium 来对他们网站的 UI 来测试... 但是他们的应用依然很烂,而且每次改变 UI 测试都会崩溃。
这个测试并没有改变产品的质量,相反浪费了程序员的时间来维护测试。
他们做错了什么?
说我们都需要写出高质量的软件并不能帮助解决这些问题。
那我们回头来更加深入的讨论一下。
康熙字典 :) )里告诉我们测试是为了 “举证,通过一定原则或标准或实验来,证明真理,真实性。“
软件质量就在那里,是的,但事实却又不仅如此。
准确的说,这只是英语定义,可以肯定,有很多不说英语的开发者。
我不想被字典来束缚我们的行为。
人类语言是数世纪以来对世界的观察和理解,也是我们可以拿来借鉴的宝库。
那我们来以这个为出发点来看看能学到点什么。
下面这个是测试吧?
def test_add():
assert add(2, 2) == 5
没错,他还真是,没毛病。
看函数名,一点都没错。
测试说明 add()
做了他该做的:将两个数相加得到结果。
你注意到这个测试是错的。
幸运的是我们的开发流程进入到了另一步:代码审查。
亲爱的读者们,代码审查告诉我我的代码是错的,2 + 2 = 4,不是 5。
代码审查是不是测试的一种?
根据字典定义来说是的:代码审查就是根据标准来验证代码的 “正确,真实性和质量”,这个从小我们就知道。
那我们假设代码审查跟单元测试一样都是测试的一种。
他们都是测试,却又相当不同。
那主要的区别在哪里?
一种是自动化的,一种是人来做的。
自动化测试具有一致性和可重复性。
你可以这样写:
def test_add_twice():
for i in range(10000000):
assert add(i, i) == 2 * i
电脑每次都跑一遍一摸一样的代码。
代码可以保证根据输入每次调用add()
返回他们的结果。
人在手动验证一千万种不同的计算时会遇到一些困难,比如无聊、分心、失误、缓慢啦等等。
另一方面,任何人都可以很快的告诉你下面的代码是错的:
def add(a, b):
return a + b + 1
计算机只按照指令执行操作,孰对孰错,人类能赋予它意义。
只有人才知道软件是为何而生。
现在我们知道每种测试的不同,以及如何组织它:人类来发现意义,自动化测试确保一致性。
我们来看一下测试的另一个方面。
“A/B 测试”是一种尝试不同分类来看哪种结果更好的测试。
比如你为了测试网站新的设计:给 90% 的访问者原有的设计,同时给 10% 的访问者新的设计,看看哪种注册人数多一点。
这是测试吗?
这就叫 “A/B 测试”,跟它的名字一样。
我们来重新看一下字典定义:“举证,通过一定原则或标准或实验,来证明真理,真实性。”
字典上说这也是测试,因为通过实验。
我们通过实验来看看哪个版本更受欢迎。
单于测试和代码审查,对比来说,就是通过一定原则或标准来测试。
我们对软件有一些特定规格,一些我们希望软件的行为,同时我们确保它符合规格。
现在我们有了第二种理解与组织测试的方法:通过实验测试 vs 针对规格测试
将它们放在一起我们得到下面这张关于测试的图表:
这些都是无法通过软件是否符合规格来回答。
相反需要你的经验知识:你需要观察人对软件的真实反映。
这些问题不能通过对比规范来解答,
你需要把软件跑起来看看到底会发生什么。
很容易说自动化的测试可以证明这一点,但有没有想过单元测试在检查 2 + 2 = 5。
在基本的层面上,软件可以在技术上符合规范却完全无法达成规范的初衷。
但只有人明白规范的含义,和辨别是否匹配这个规范。
人不是测试这个问题的好办法。
所有人都会忽略小问题:如果一个按钮从 “Send Now” 变成 “Send now”,很多人都不会注意到。
对比来说,如果你的 API 从 sendNow()
变成 send_now()
,或者返回一个不同类型的值,你的软件就会崩溃。
这就是说公有的 API,或者其他软件依赖的 API,需要稳定性来确保正确性。
为私有的接口写自动化测试,或者对于迭代较快的代码,更新测试将导致极高的维护成本。
如何应用模型?
首先,模型可以帮助你根据你的目标选择合适的测试。
如果一家初创公司做一个没人用的软件。
写自动化测试纯属浪费时间,因为他连用户想要什么都不知道就开始专心实施了。
这里需要用精益创业的方法论,一个专注于用实验找到什么产品将满足客户的需求的方法来解决。
这意味着专注于用户行为象限。
只有证明他值得花费时间来进行下去,才值得对这个产品来做一些为了功能性和稳定性的测试。
第二,这个模型可以帮助你改变错误的行进路线。
比如说那家初创的税务公司,如果他们对于 UI 进行自动化测试但是并没有发现问题,然后每改变一次 UI,整个系统都要重新来进行一遍测试。
他们的问题在于系统的两个方面:
最后,这个模型提供了一个公有的术语,来讨论的测试的意义及其不同的目标。