软件测试常识
软件测试应该跨越整个软件开发流程。需求验证(自检)和设计验证(自检)也可以算作软件测试(建议称为需求测试和设计测试)的一种。软件测试应该是一个泛型概念,涵盖整个软件生命周期,这样才能确保周期的每个阶段都禁得起考验。同时测试本身也需要有第三者进行评估(信息系统审计和软件工程监理),即测试本身也应当被测试,从而确保测试自身的可靠性和高效性。否则自身不正,难以服人。
软件开发和使用的历史已经留给了我们很多由于软件缺陷而导致巨大财力、物力损失的经验教训。这些经验教训迫使我们必须采取强有力的检测措施来检测未发现的隐藏软件缺陷。生产软件的最终目的是为了满足客户需求,我们以客户需求作为评判软件质量的标准,认为软件缺陷(Software Bug)的具体含义包括下面几个因素:
- 软件未达到客户需求的功能和性能。
- 软件超出客户需求的范围。
- 软件出现客户需求不能容忍的错误。
- 软件的使用未能符合客户的习惯和工作环境。
考虑到设计等方面的因素,我们还可以认为软件缺陷包括软件设计不符合规范、未能在特定的条件(资金、范围等)达到最佳等。可惜的是,很多人更倾向于把软件缺陷看成运行时出现的问题,认为软件测试仅限于程序提交之后。在目前的国内环境下,几乎看不到完整准确的客户需求说明书,再加上客户的需求时时在变,追求完美的测试变得不太可能。但是明确软件测试现实与理想的差距,在软件测试中学会取舍和让步,对软件测试是有百益而无一弊的。
7.2 系统功能测试计划
软件测试并不单纯等同于程序测试。软件测试应该贯穿整个软件定义与整个开发周期。因此需求分析、概要设计、详细设计以及程序编码等各阶段所得到的文档,包括需求规格说明、概要设计规格说明、详细设计规格说明以及源程序,都应该是软件测试(评审)的对象。
在对需求理解与表达的正确性、设计与表达的正确性、实现的正确性以及运行的正确性的验证中,任何一个环节发生了问题都可能在软件测试中表现出来。
在这部分中,我个人确保每个阶段功能的实现,在系统完成后,每个分支都走过一遍,也有发现的问题,但都通过查阅资料将其解决了。
7.3 性能测试
测量Web服务器的性能是一项让人感到畏缩的任务,它不像一些简单的任务,如测量CPU的速率或者是测量程序占用CPU的比例,Web服务器的性能优化中包括调整许多变量来达到目标。许多的测量策略中都包含了一个看似简单的浏览,实际上是在向服务器发送大量的请求,这称之为客户端的程序,它用来测量响应时间。常见的问题有如下几个:
- 客户端和服务器端是在同一台机器上吗?
- 服务器在测试的时候还运行着其他的程序吗?
- 客户端和服务器端的通信是通过局域网(100baseT、10baseT)还是使用调制解调器?
- 客户端是否一直重复请求相同的页面,还是随机地访问不同的页面?
- 客户端发送请求是有规律的还是突发的?
- 是在最终的配置环境下运行服务的?还是在调试的配置环境下运行服务的?
- 客户端的请求中包含图片还是只有HTML页面?
所有这些都是要关心的问题,并且几乎不可能精确地把所有的问题都列出来。
一般衡量Web性能的重要指标有以下几个:
- HTTP每秒交易数(Transaction Per Second)。
- 每秒会话数(Sessions Per Second):每秒到达Web服务器的用户。
- 并发用户数(Concurrent Users):特定时间在Web站点上的用户数。
- 吞吐量(Throughput):在特定时间内由Web站点发出的数据流量带宽,它与服务器提供服务的内容和交易数相关。
基于以上的要求,最合适的测试方法无非是通过一定的访问量来实现,但是这样的工作谈何容易,这种思路的测试就是压力测试。俗话说:“工欲善其事,必先利其器”,压力测试只有借助于一些工具才可得以实施。大多数Web压力测试工具的实现原理都是通过重复的大量页面请求来模拟多用户对被测系统的并发访问,以此达到产生压力的目的。产生压力的手段都是通过录制或者是编写压力脚本,这些脚本以多个进程或者线程的形式在客户端运行,这样通过人为制造各种类型的压力,可以观察被测系统在各种压力状况下的表现,从而定位系统瓶颈,作为系统调优的基础。目前已经存在的性能测试工具林林总总,数量不下一百种,从单一的开放源码的免费小工具,如Apache自带的Web性能测试工具(Apache Benchmark、开源的JMeter)到大而全的商业性能测试软件,如Mercury的LoadRunner、Siege等。
Apache JMeter是一个专门为运行和服务器装载测试而设计的100%的纯Java桌面运行程序。最早它是为Web/HTTP测试而设计的,但是现在它已经扩展,从而支持各种各样的测试模块。它和用于HTTP和SQL数据库(使用JDBC)的模块一起运送。它的功能举例如下:
- 用来测试静止资料库或者活动资料库中的服务器的运行情况。
- 用来模拟对服务器或者网络系统加以重负荷,以测试它的抵抗力。
- 用来分析不同负荷类型下的所有运行情况。
- 它还提供了一个可替换的界面用来定制数据显示,测试同步及测试的创建和执行。
- 用于测试静态或者动态资源的性能(如文件、Servlets、Perl脚本、Java对象、数据库和查询、ftp服务器或者其他的资源)。
- 用于模拟在服务器、网络或者其他对象上的附加高负载以测试它们提供服务的受压能力。
总之,你可以用JMeter提供的图形化界面分析性能指标或者在高负载情况下测试服务器、脚本、对象的行为。
下面是我模拟的几组测试数据,测试页面:前台产品展示→女装,假定该页的访问量为10次/秒,测试报告如表7.1所示。
表7.1 测试报告1
模拟用户数 | 访问次数 | 样本数目 | 平均响应时间 | 并发访问 | Bytes |
1 | 1 | 1 | 297 | 否 | 13409 |
1 | 20 | 20 | 335 | 否 | 13409 |
1 | 50 | 50 | 311 | 否 | 13409 |
1 | 100 | 100 | 326 | 否 | 13409 |
1 | 1000 | 1000 | 328 | 否 | 13409 |
5 | 1 | 5 | 1484 | 否 | 13409 |
5 | 1 | 5 | 1443 | 是 | 13409 |
20 | 1 | 20 | 4375 | 否 | 13409 |
20 | 1 | 20 | 6094 | 是 | 13409 |
100 | 1 | 100 | 21330 | 否 | 13409 |
测试页面:前台产品展示→女装,假定该页的访问量为1次/秒,测试报告如表7.2所示。
表7.2 测试报告2
模拟用户数 | 访问次数 | 样本数目 | 平均响应时间 | 并发访问 | Bytes |
1 | 1 | 1 | 297 | 否 | 13409 |
1 | 20 | 20 | 297 | 否 | 13409 |
1 | 50 | 50 | 312 | 否 | 13409 |
1 | 100 | 100 | 295 | 否 | 13409 |
1 | 1000 | 1000 | 313 | 否 | 13409 |
5 | 1 | 5 | 234 | 否 | 13409 |
5 | 1 | 5 | 1453 | 是 | 13409 |
20 | 1 | 20 | 235 | 否 | 13409 |
20 | 1 | 20 | 5737 | 是 | 13409 |
100 | 1 | 100 | 260 | 否 | 13409 |
1000 | 1 | 1000 | 320 | 否 | 13409 |
通过测试,可得以下结论:
- 现在我们把所有的信息都归结到平均响应时间的需求上来,根据上面测试得到的数据,发现几个非常大的响应时间都是并发访问情况下得到的,在并发情况下JMeter将会在测试的开始就建立全部线程并立即发送访问请求,这样一来就很容易使服务器饱和,更重要的是会隐性地增加了负载,服务器将可能过载,不是因为平均访问率高而是因为所有线程的第一次并发访问而引起的不正常的初始访问峰值,可以通过JMeter的聚合报告监听器看到这种现象。这种异常,虽然不是我们测试所需要的,但是这提示了我们一个问题,可能会面对这样的服务器攻击。
- 平均响应时间会随着每秒访问次数的增大而增大,所以能够模拟到网站的平均点击率,对于这个压力测试是很有帮助的。在1次/秒的访问量下,平均响应时间大约在260ms。