(点击上方公众号,可快速关注)
编译:伯乐在线/Anne90
如有好文章投稿,请点击 → 这里了解详情
你为什么应该测试你的软件?你应该如何测试软件?有些人对这些问题有非常简单的回答。
及时享乐型的程序员根本懒得去测试,快乐地活在当下。更严肃的程序员会告诉你软件测试是为了开发出高质量的产品。为了可以开发出高质量的产品,必须始终编写单元测试和集成测试,并做 QA 测试。忽略这些,你的代码将会掉入 bug 为患的深渊。
尽管我更赞同第二种观点,但我认为这不是一个完美的答案。考虑到不同的软件项目的差异,一套答案似乎不可能适合每个人。
你需要的不仅仅是一个答案,而是如何去选择适合你情况和需要的答案。我们首先会考虑适合你的测试方法。然后我们会考虑为什么要测试你的软件。最后,我们将结合方法和目标,来看一下你可以选择什么方式去测试你的软件。
你可以用什么样的测试方法?
首先,我们考虑下可以使用的不同测试方法。下面的代码是测试吗?
def test_add():
assert add(2, 2) == 5
我会说,是的,那就是一个测试。从函数名上可以看出来。这个测试证明了函数add() 做了什么:对两个数字做加法,然后将结果返回给我们。
你一定注意到了,这个测试是错误的。幸运的是,我们的开发过程有另一步骤:代码审查。亲爱的读者,你可以作为一个代码审查者并告诉我,我的代码是错误的,2加2是4,不是5。
代码审查是一种测试方法吗?如果你试图验证你的代码符合规范,那么这就是一种测试。你大脑中有算术规范(”2 + 2 = 4″),你就会检查你的代码是否符合这个规范。
让我们把代码审查和自动化单元测试都做分别作为一种测试方法。尽管他们都是测试,他们也非常不同。他们之间的主要区别是什么?
测试的一种方法是自动化的,另一种是由人类完成的。
自动化测试是连续的和可重复的,你可以这么写:
def test_add_twice():
for i in range(10000000):
assert add(i, i) == 2 * i
计算机将会每次运行完全相同的代码,该代码将会确保函数 add() 对于这些特定的输入返回特定的输出。人在手动验证一千万种不同的计算时会遇到一些困难:无聊、分心、错误、迟缓。
另一方面,人类在阅读这个代码时,会告诉你这是bug:
def add(a, b):
return a + b + 1
计算机所做的事情,无论是好是坏,人类都能明白他的意义。只有人类才知道软件的意义是什么。
现在我们可以按照使用的方法来对测试进行分类:人类测试意义,自动化测试确保一致性。
你为什么要测试软件?
接下来,让我们考虑测试目标。
测试软件的第一个可能的目标就是确保它符合规范。这个目标是大多数程序员在讨论测试时想到的:它涵盖了单元测试和手工测试,它也包括代码审查。你的软件具有某些必须的功能、规范,你想确保它在现在和未来也确实是这样的。
一些需求是高层次的:一个在线商店想要顾客可以订购他们添加到购物车的产品。其他需求是低层次的实现细节,只有程序员感兴趣。你可能想要函数 verify_creditcard() 接收信用卡号码作为字符串,然后如果信用卡是无效的,抛出一个 InvalidCreditCard 异常。
所有的这些需求都是规范,他可以被写的非常详细,也可以是头脑中的一个概念(如 2 + 2 等于 4 )。无论如何,你测试你的软件是为了确保它做了它应该做的事。
然而,有时测试也可以有不同的目标。在 Eric Ries 的书《精益创业》中, 他提到编写软件后却发现没有人真正想用它的问题。如果没有人使用你的软件,花费了大量的时间去测试,确保你的软件满足规范就是浪费时间。
Ries 认为你首先应该搞清楚一个产品是否会成功,通过测试他称为的“最低可行产品”是否拥有潜在的用户和客户。这是一个与众不同的测试形式:它不是验证你的软件是否满足规范,而是学习你以前不知道的东西。
软件测试第二个可能的目标就是为了获得知识。让我随着这个目标看一下另一种测试形式。“A/B测试”就是你使用两个变量,然后看哪个变量产生更好的结果。或许你正在测试重新设计的网站:你给 90% 的访客展现你目前的设计,10% 的访客展现你的新设计,然后看哪种会让你的产品有更多的用户注册。
注意,你有两套规范,并且已经实现了他们。测试的要点就是找到哪种规范更好,学习一些新的东西,而不是验证实现是否符合规范。
现在我们已经知道为什么你需要做测试:要么验证你的实现符合规范,要么获得新的知识。
你应该如何测试软件?
结合我们提出的那两个目标(获得新知识和满足规范)和两种测试方法(手工测试和自动化测试),你会得到四种不同的测试形式,每种都会有更详细的测试目标。
对于你特定的需求和情况,你必须选择一种合适的测试方式。让我们逐个介绍这四种测试类型,看看每种测试类型应该在什么情况下使用。
理解用户
用户会购买你的产品吗?
一个设计的改变会带来有更多的注册吗?
用户会理解你的软件是如何工作的吗?
这些问题都无法通过对比你的软件是否满足规范来得到回答。相反,你需要经验知识:你需要观察当你的软件展现给用户时,用户真正做了什么操作。
相关的测试技术包括:
可用性测试
最低可行产品测试(《精益创业》)
A/B测试
理解运行时行为
你的软件在负载下的表现如何?
你的软件有资源竞争吗?
当有非法输入时,你的软件是否会崩溃?
这些问题不能总是通过比较你的软件是否符合规范来回答。一旦你的软件足够复杂,你无法完全理解或者预测它的回应。你需要观察它的实际运行来理解其行为。
相关的测试技术包括:
功能的正确性
你的软件是否真正符合规范?
你的软件是否做了它应该做的事?
很容易可以看到,自动化测试可以证明这些,但是请记住检查2+2等于5的单元测试。在更基本的层面上,软件可以在技术上满足规范,但是不能达到规范的目标。只有我们理解规范背后的含义,然后才能确定软件是否达到了目标。
相关的测试技术包括:
手动用户界面测试(如:QA人员使用您的网站)
代码审查
功能的稳定性
人类很不擅长测试这些情况。人类非常容易忽略小的变化:如果一个按钮从“Send Now”改变为“Send now”,你可能根本就不会注意到。相反,如果你的接口从sendNow() 变为 send_now(),或者返回值的类型有轻微变化,你的软件就会崩溃。
这意味着一个公开接口,尤其是其他软件依赖的接口,为了保证正确性必须要稳定。当你不断更新你的测试时,为改变频繁的私有接口或者代码编写自动化测试,将会导致非常高的维护成本
相关的测试技术包括:
模型的应用
那么这一切有什么好处呢?
选择如何去测试
首先,我们最初的目标:基于你的目标,这个模型可以帮助选择测试形式。
考虑一个新建立的产品,不确定什么样的人愿意使用这个产品。自动化测试的重点在于确保代码符合规范,因此在搞清楚用户真正的需求之前,编写自动化测试用例可能是浪费时间。
精益创业(Lean Startup)是一种可行的替代方法,它的目标是找到什么样的产品可以满足用户的需求,它侧重于实验或者尝试。这意味着专注理解用户这个象限。一旦选定了产品,你就可以花费时间在确认“最低可行性”之外的地方,比如投入更多的资源保证软件功能的正确性和稳定性。
辨别你是否选择了错误的测试类型
第二,当你选择了错误的测试类型时,这个模型可以帮你改变航向。比如假设编写税收软件(细节源自一个真实案例),他们为他们的web界面编写了Selenium测试,与此同时他们的web界面做了重大的改变。
即使做了测试,他们的程序依然是有bug的,每次改变界面这些测试用例就不能使用了。测试似乎没有提升质量,但是它浪费了开发者的时间进行维护。他们做错了什么?
这个问题就是他们的系统实际上有两部分:
税收引擎相当稳定,税法每年只改变一次。对于用户来说税收引擎中的错误是一个主要问题,对于开发者来说不兼容的接口改变是一个问题。这表明需要稳定的功能测试,比如针对税收计算引擎的单元测试。正确的功能可以通过代码审和查税务会计的反馈来保证。
基于web的用户界面。UI界面频繁的变更,这表明稳定的功能测试现在还不是目标。现在的目标是功能的正确性,所以UI界面应该进行手工测试(比如:当程序员写代码时进行测试)
讨论测试的基础
最后,这个模型提供了一个共享的术语,这个术语可以帮助你在广泛的意义和不同的目标下讨论测试。
总结
你为什么要测试你的软件?要么获得知识,要么满足规范。
你测试软件的方法有哪些?手工测试或者自动化测试。
你应该如何测试你的软件?根据你特定的情况,选择相关的测试形式,如理解用户、理解运行时行为、功能的稳定性、功能的一致性。
看完本文有收获?请分享给更多人
关注「伯乐在线」,看更多精选 IT 职场文章