1.1 软件系统开发的可靠性问题
在20世纪70年代以前,软件对于大多数人来说,还是个新鲜名词。人们只能在政府机构、科研院所、军事机构以及大型企业里才能看到体积庞大、操作复杂的大型计算机以及运行在它们之上的软件系统。从70年代末开始,以微软和IBM为代表的软件、硬件厂商将计算机带进了人们的日常生活。从那以后,软件的发展可谓日新月异,迅速渗透到各个行业。时至今日,软件在我们的日常生活中已经司空见惯,PC、笔记本计算机、平板电脑、智能手机等,无一不是以软件为基础的。小到肉眼难以看清的微型芯片,大到关系国家安全的国防军事工业,软件都按照人们既定的设计,支撑着这个世界的运转。
今天在世界各地,软件都太重要了。一旦软件出现故障,就会造成损失,甚至是灾难。2007年11月11日,美国洛杉矶国际机场海关的计算机发生故障,导致60多个航班受到影响,2万多名旅客滞留在飞机上和候机楼,无法入关,14个小时后计算机故障才得到解决。EDS是美国著名的电子数据系统公司,英国国内收入局曾选择该公司为其设计内部计算机系统。2004年,由于该公司设计的计算机系统不完善,英国税收抵免陷入混乱,造成10亿英镑的损失。在中国,也不乏软件缺陷造成重大损失的例子。2011年,号称“全球最大的中文IT社区”的网站csdn.net被黑客入侵,众多该网站用户的登录信息被黑客打包上传到互联网上。由于现在很多互联网用户在多个网站使用同样的用户名和密码,他们不得不去更改其他网站的密码。而csdn.net将用户密码用明文的形式存储于数据库,也被业内人士嘲笑为“极其不专业和不负责任”。
软件如此重要,软件缺陷造成的影响如此重大,因此保证软件质量就显得尤为关键。软件测试,作为保证软件质量最常用的手段[1],被很多公司和机构釆用。微软公司的测试人员和开发人员的比例一般为1∶1[2],而在Windows 2000开发团队中,有1 800名测试人员,900名开发人员,测试人员和开发人员的比例达到了2∶1。在谷歌公司,测试人员和开发人员的比例一般为1∶10。微软和谷歌两家公司测试人员和开发人员的比例差距如此之大,原因是:在微软,工作量巨大的单元测试工作是由测试人员完成的;而在谷歌,单元测试则是开发人员的职责。在国内的龙头企业阿里巴巴,测试人员和开发人员的比例大致为1∶4,而在其子公司蚂蚁金服,由于涉及对安全性要求更高的互联网金融行业,其测试人员和开发人员的比例达到了1∶3,且还有逐年递增的趋势。
就像制造行业每一道工序后都有质检过程一样,软件开发的每一个阶段都有对应的测试环节。以传统软件开发常用的模型为例,软件的开发过程被分为需求分析、概要设计、详细设计、编码阶段。与之对应,软件测试被分为单元测试、集成测试、系统测试、验收测试[3]。而在一些要求更高的系统中,还会涉及性能测试、压力测试、容量测试、兼容性测试、安全性测试等。在这一系列的测试中,单元测试是最低级别的测试活动,它的目的是检测程序模块有无故障存在。也就是说,在基础的测试阶段,不是把程序作为一个整体来测试,而是集中精力测试程序中较小的结构块,以便发现并纠正模块内部的故障[4]。通过单元测试的程序,能够确保每一个模块正确运行,后续的测试如集成测试、系统测试等都是在每个模块能正确运行的基础之上进行的。因此,单元测试是耗时最多、发现问题最早也最多、修复问题成本最低的测试。(https://www.daowen.com)
软件测试是伴随着软件的产生而产生的,在早期的软件开发过程中,由于软件规模小、复杂度低,也没有形成通用的开发模型,人们通常把软件测试等同于调试,这部分工作常常由开发人员自己完成。
到了20世纪80年代初期,软件进入了快速发展阶段,软件向大型化、复杂化方向发展[5]。这时,一些软件测试的基础理论和实用技术开始形成,软件测试进入了正规化、结构化的阶段。这个阶段的测试是以人工测试为主,人工编写测试用例,人工执行测试用例,人工统计测试结果。人工测试有一个优势——人的思维。对于一些逻辑性很强的软件,人可以在测试的过程中从不同的角度来思考问题,使得设计的测试用例能更好地覆盖软件的功能。
然而,人工测试的代价也是高昂的。测试会遇到许多重复性的工作,重复完成同一项工作,被很多人视为没有价值或者没有挑战的工作。现代软件的规模决定了测试工作量巨大,测试人员在长时间的工作后,会出现疲劳、注意力下降等情况,这不仅导致工作效率下降,也容易导致错误产生[6]。
而自动化测试可以弥补上述缺陷,程序按照人们的设定有条不紊地运行,完成测试工作,它不会觉得重复的工作毫无挑战,也不会因为连续运行数小时而降低精度、产生错误。因此,自动化测试是软件测试发展到一定阶段的必然产物,是软件测试发展的方向。和人工测试相比,自动化测试的优势显而易见,例如,它能够提高测试效率和降低测试成本,将重复性测试独立出来。自动实现快速的回归测试可以避免人工测试容易犯的错测、漏测、多测等错误,模拟人工测试几乎无法办到的多用户并发场景[7]。