前面已经说过,对于互联网应用软件,性能是其质量的一个非常重要的组成部分。作为解决软件性能问题的重要手段,软件性能测试已经广为人们所熟悉,并受到很高的关注。一般而言,性能测试都是在项目的后期才开展,被测试的对象通常是已经具备一定稳定性的产品。而实际上,性能测试应贯穿于整个软件生命周期中,和功能测试一样,性能测试也分为几个阶段。
软件生命周期与性能测试
不论哪种软件生命周期模型,需求分析、设计、编码、测试和运行维护这几个阶段都是其中的基本要素,只是在不同的软件生命周期模型中可能迭代、合并、拆分或重组这几个阶段,在此不做过多的描述。与其他几个阶段相对应,测试从软件开发过程按阶段可以划分为:单元测试、集成测试、系统测试,在其他的书上可能还能见到诸如确认测试、验收测试等名词,但是前3种测试确实是最基本的测试活动,而其他的测试活动只是在某些软件开发过程中会发生。
值得注意的是,通常在谈论单元测试、集成测试和系统测试时,其实仅仅谈论的是不同阶段的功能测试;而当讨论性能测试时,绝大多数的情况是,一个已经开发完毕或基本开发完毕的软件,测试人员用一种或几种性能测试工具,以尽量模拟真实用户行为的方式对该软件进行并发操作,收集并比较不同场景的结果,然后对软件的性能进行分析,这个活动通常发生在系统测试阶段,甚至更往后的阶段,如运行维护阶段。
一直以来,性能测试跟单元测试、集成测试似乎都是绝缘的。可是它们真的应该是绝缘的吗?没有任何理由可以说明性能测试跟单元测试、集成测试无关,除非你认为“这太难了,我不会做”(这正好是本章主要想说的)或者“做这个没什么意义,浪费时间”(那么请接着往下看)。
众所周知,把测试划分为单元测试、集成测试和系统测试,而不仅仅是在最后关头做一个系统测试,其主要原因有两点:
1.同样的缺陷在不同阶段被发现,其修复成本差异极大,而越早发现缺陷,修复成本越小;
2.某些缺陷几乎只能在某个阶段被发现,即在其他阶段需要投入巨大的人力才能发现这些缺陷或根本不可能发现这些缺陷。
简而言之,对于不同阶段的测试活动,总有一些缺陷是最适合被发现和修复的。对于功能性缺陷这点早已达成共识,而对于性能性缺陷,由于性能测试本身起步较晚、性能问题比较难以暴露、早期用户对性能问题容忍度比较高、商业性能测试工具价格昂贵等原因,很多时候可能根本不会进行性能测试,或仅进行比较简单的性能测试,因此虽然性能性缺陷同样有这个特性,但却被人们遗忘了。简单地列举几个在不同阶段进行性能测试的好处。
1.在单元性能测试中运行一遍后就能发现的内存泄漏问题,如果这个问题遗留到系统测试阶段,可能需要花费几天的时间才能找到问题的所在,尤其是当Dump 内存信息后发现大量对象是到处都在使用的基本对象时,欲哭无泪可能是性能优化人员此时的真实写照,这点笔者曾有幸体验过;而实际上运行一遍单元测试的时间可能也就几分钟,此时发现问题极易解决。
2.异构系统之间的接口,通常是先完成接口,而调用接口的系统可能过很久才会完成。当然,可以等完成调用接口的系统后直接对该系统进行测试,接口的性能自然被测试到了,但是万一很不幸——性能测试结果不佳,再花费一番力气后终于确定是接口性能不佳,那可能就得大费周折地重新写接口了。更倒霉的是别的系统已经在用新的接口了,而不巧的是新老接口又不兼容(比如差一个参数什么的),那代价可就大了;如果进行过接口性能测试,问题早就发现并解决了,这时候真是想想都会笑了。
3.越早开始性能调优,调优工作就会越容易。当组件小规模的集成后即可运行并调优时,由于系统复杂度低,自然而然地性能调优的难度会比较低。很显然,性能调优是以性能测试为基础的,那么较早阶段的性能测试就很有必要了。
4.在运行维护阶段,系统已经在稳定地为用户提供服务了,这时候还需要进行性能测试吗?需要。因为生产系统可能会表现出疑似性能问题的症状,这时候性能测试是查找问题的有效手段,有助于为用户提供更好的服务;性能再好的系统也会有极限,当用户数不断增长的时候,通过性能测试来评估系统的容量,以确定系统应如何进行扩容或者需要更换新的架构,通常这称之为容量评估。
很明显,性能测试和功能测试一样贯穿于多个阶段。基本上,各阶段的性能测试包括以下几种:单元性能测试、集成性能测试、系统性能测试、多系统性能测试、容量评估、接口性能测试。接下来看看这些不同阶段的性能测试活动到底做些什么。