1 测试的由来
黑格尔说过,”What is rational is actual and what is actual is rational.“
那么软件测试存在的原因是什么呢?世上本没有软件测试,BUG多了也就出现了。
一说到BUG,立马想到1945年Mark II计算机因飞入一只飞蛾导致死机的故事,于是后人将计算机和软件错误戏称为虫子。但是这只是开始,随机计算机的普及,随着信息技术的发展,虫子越来越多,就如同不断繁殖的蝗虫一样,渐渐影响到人们的日常生活与工作。
比如一百度就能知道的,迪斯尼狮子王游戏、英特尔奔腾浮点除法缺陷、美国航天局火星极地登陆者号着陆火星时失踪、千年虫等等。再看看国内的,2012年国庆抢票,12306提示出票失败;京东商城充值平台漏洞,损失2亿多。当人们意识到BUG带来的这般灾难性的损失时,便不能坐视不理了,于是开启了漫长的人虫大战序章。
2 软件测试心理学与经济学
注:此段文字摘录自Glenford J.Myers《The Art of Software Testing》
软件测试的心理学
测试执行得差,其中一个主要原因在于大多数的程序员一开始就把“测试”这个术语的定义搞错了,他们可能会认为:
软件测试就是证明软件不存在错误的过程
软件测试的目的在于证明软件能够正确完成其预定的功能
软件测试就是建立一个“软件做了其应该做的”信心的过程
这些定义都是本末倒置的。
每当测试一个程序时,总是想为程序增加一些价值。通过测试来增加程序的价值,是指测试提高了程序的可靠性或质量。提高了程序的可靠性,是指找出并最终修改了程序的错误。因此不要只是为了证明程序能够正确运行而去测试程序;相反,应该一开始就假设程序中隐藏着错误(这种假设对于几乎所有的程序都成立),然后测试程序,发现尽可能多的错误。
那么,对于测试,更为合适的定义应该是:“测试是为发现错误而执行程序的过程”。
人类行为总是倾向于具有高度目标性,确立一个正确的目标有着重要的心理学影响。如果我们的目的是证明程序中不存在错误,那就会潜意识中倾向于实现这个目标,也就是说,我们会倾向于选择可能较少导致程序失效的测试数据。另一方面,如果我们的目标在于证明程序中存在错误,我们设计的测试数据就有可能更多地发现问题。
这种对软件测试的定义,暗示了软件测试是一个破坏性的过程,甚至是一个“施虐”的过程,这就说明为什么多数人都觉得它困难。这种定义可能是违反我们愿望的,所幸的是,我们大多数人总是对生活充满建设性而不是破坏性的愿景。大多数人都本能地倾向于创造事物,而不是将事物破坏。
一个成功的测试用例,通过诱发程序发生错误,可以在这个方向上促进软件质量的改进。当然,最终我们还是要通过软件测试来建立某种程序的信心:软件做了其应该做的,未做其不应该做的。但是通过对错误的不断研究是实现这个目的的最佳途径。
有人可能会声称“本人的程序完美无缺”,针对这种情况建立起信心的最好办法就是尽量反驳他,即努力发现不完美之处,而不只是确认程序在某些输入情况下能够正确地工作。
软件测试的经济学
一般说来,要发现程序中的所有错误是不切实际的,常常也是不可能的。这个基本的问题反过来暗示出软件测试的经济学问题、测试人员对被测试软件的期望,以及测试用例的设计方式。
穷举输入测试无法实现,说明:1)我们无法测试一个程序以确保它是无错的,2)软件测试中需要考虑的一个基本问题是软件测试的经济学。也就是说,由于穷举测试是不可能的,测试投入的目标在于通过有限的测试用例,最大限度地提高发现的问题的数量,以取得最好的测试效果。
3 软件测试的原则
测试用例必须定义预期输出结果
如果某个测试用例的预期结果事先没有得到定义,由于“所见即所想”现象的存在,某个似是而非,实际上是错误的的结果可能会被解释成正确的结论。
换句话说,尽管“软件测试是破坏性”的定义是合理的,但人们在潜意识中仍然渴望看到正确的结果。克服这种倾向的一种方法、就是通过事先精确定义程序的预期输出,鼓励人们对所有的输出进仔细检查。程序员应当避免测试自己编写的程序
如果我们对软件项目关注的重点发生变化,就会产生另外一个问题。当程序员“建设性”地设计和编写完程序之后,很难让他突然改变视角以一种“破坏性”的眼光来审查程序。
大多数程序员都不能有效地测试自己编写的程序,因为他们无法改变思维方式来尽力暴露自己程序中的错误。另外,程序员可能会下意识地避免找出错误来,担心受到同事、上司、客户或正在开发的程序或系统的主管的惩罚。
还有一个重要的问题,由于程序员错误地理解了疑难定义或规范,导致程序中存在错误。如果情况是这样,程序员可能会带着同样的误解来测试自己的程序。测试用例编写不仅应当根据有效和预期的输入情况,而且应当根据无效和未预料的输入情况
在测试软件时,有一个自然的倾向,即将重点集中在有效和预期的输入情况上,而忽略了无效和未预料到的情况。
在软件产品中突然暴露出来的许多问题是当程序以某些新的或未预料到的方式运行时发现的。因此,针对未预料到的和无效输入情况的测试用例,似乎比针对有效输入情况的那些用例更能发现问题。程序某部分存在更多错误的可能性,与该部分已发现错误的数目成正比
错误总是倾向于聚集存在,而在一个具体的程序中,某些部分要比其他部分更容易存在错误,尽管没有人能够对这种现象给出很好的解释。这种现象之所以有用.是因为它给予了我们对软件测试过程的洞察或反馈。如果一个程序的某个部分远比其他部分更容易产生错误.那么这种现象告诉我们,为了使测试获得更大的成效,最好对这些容易存在错误的部分进行额外的测试。
4 测试 ≠ 质量
测试的目的是尽可能多地发现问题,从而提高软件的质量。因此Bill Hetzel在《The Complete Guide to Software Testing》书中给出了新的定义:“测试是以评价一个程序或者系统属性为目标的任何一种活动,测试是对软件质量的度量。”
Myers强调的是测试的行为,而Bill Hetzel强调的是测试的结果。
我们潜移默化的以为经过测试的软件,质量会更高,但一定要明确,质量不等于测试。比如软件在最初设计的时候就是错的,那它永远就不会变成正确的。另一方面,测试只能发现软件的错误,但错误的修复并不在测试范围内,因此无法保证问题一定得到解决,并且解决妥当。
《Google软件测试之道》中谈到,Although it is true that quality cannot be tested in, it is equally evident that without testing, it is impossible to develop anything of quality。 还有一句话是, Quality is achieved by putting development and testing into a blender and mixing them until one is indistinguishable from the other。我的理解是,当测试与编码合二为一时,就得到了质量。让一个人既懂测试也懂编码,过于苛刻,但如果突破测试与编码之间的工作壁垒,相互补充,也不失为一条可行之路。
5 TDD
TDD = Test-Driven Development,即测试驱动开发,还有一些类似的概念,如BDD(Behavior-Driven Development)、DDD(Domain-Driven Design)。
Wiki上对TDD的介绍是:Requirements are turned into very specific test cases, then the software is improved to pass the new tests, only. This is opposed to software development that allows software to be added that is not proven to meet requirements。
其实结合第三章,与其开发完再去打补丁,不如开始前就思考周全。结合测试对异常场景的考虑,再加上编码上的实现,相信软件质量更能符合二者的期望。
6 测试工程师的定位
完美主义
任何软件都是有问题的,包括经过测试的软件。但是没有最好,只有更好换位思考
测试人员把自己当成客户——客户怎么想,怎么做
测试人员把自己当开发——开发怎么实现,有什么思维惯性
测试人员把自己当产品——软件为什么这么设计无限可能
测试不可能穷尽,但时间有限,所以力求在有限的时间内尽可能的覆盖更多更有价值的场景技术支撑
好的测试人员要以测试方法为指导,专业技术为支撑,这样才能完成实际的,有针对性的、高效的测试工作。发现问题、分析问题、解决问题是密不可分的三部分,测试技术和专业技术的协调发展是高质量测试工作的坚实基础。创造性
想发现更有意思的BUG,就需要别出心裁的脑洞大开。
7 测试的未来
我展望的未来里,测试会开发,开发会测试,于是无所谓测试与开发。