【IT168 技术文档】目前软件性能测试是发现软件性能问题有效的手段,而完备有效的性能测试是关键的,在本节中我们将从流程和技术的角度解析如何构建一个高效的性能测试模型。
  1.2.1 性能测试在软件测试的周期位置
  首先,软件性能测试属于软件测试范畴,存在于软件测试的生命周期中。一个软件的生产过程通常遵循V型图,如图1-3所示。
图1-3 软件开发-测试V型图
  在通常的软件生产周期中,先由用户提出用户需求或经系统分析核定以后提出系统需求,开发人员再经过需求分析提出软件需求规格说明,进行概要设计,提出概要设计说明,进行详细设计,提出详细设计说明,后是对每个模块进行编码。到测试阶段,测试按照开发过程逐阶段进行验证并分步实施,体现了从局部到整体、从低层到高层逐层验证系统的思想。对应软件开发过程,软件测试步骤分为代码审查、单元测试、集成测试、系统测试。
  而性能测试属于软件系统级测试,其终目的是验证用户的性能需求是否达到,在这个目标下,性能测试还常常用来做:
  (1)识别系统瓶颈和产生瓶颈的原因;
  (2)优化和调整平台的配置(包括硬件和软件)来达到高的性能;
  (3)判断一个新的模块是否对整个系统的性能有影响。
  系统瓶颈:
  瓶颈本来是指玻璃瓶中直径较小并影响流水速度的一段,用它来比喻软件系统中出现性能问题的节点是很形象的,比如一个典型的分布式系统架构如图1-4所示。
 图1-4 软件系统压力流动图
  如果把软件系统看做是交通系统,那么网络是一条条大道,客户端、防火墙、负载均衡器、Web服务器、应用服务器(中间件)、数据库等各个系统节点是交通要塞,客户的请求和数据像在道路上行驶的车辆,如果在某处发生堵车,那么整个交通系统都会不畅。在这个时候,我们要分析是哪里出了问题,是道路不够宽,还是某处立交桥设计不合理而引起堵塞等。找到问题的关键点,那么此关键点是本系统的瓶颈。软件系统也是如此,我们做性能测试的大部分工作都是为了寻找这个瓶颈到底在何处。
  需要注意的是,软件的性能瓶颈可能不止一处。
  作为软件测试的一种,软件测试的规则同样适用于性能测试中:
  (1)确定预期输出是测试必不可少的一部分
  如果事先无法肯定预期的测试结果,往往会把看起来似是而非的东西当作正确结果。必须提倡用事先精确对应的输入和输出结果来详细检查所有的输出。对于性能测试来说,预期输出是用户的性能需求,一份明确的性能需求是成功性能测试的先决条件。
  (2)必须彻底检查每一个测试结果
  事实上,在终发现的错误,有相当一部分在前面的测试中已经暴露出来了,然而由于人们未能细心检查先前的测试结果而遗漏了。
  一段程序中存在的错误概率与在这段程序中发现的错误数呈正比。
  这是pareto原则应用于软件测试,也包括性能测试,即性能测试发现的错误中的80%很可能集中在20%的程序模块中。
  (3)穷举测试是不可能的
  在性能测试中不可能覆盖每一个功能部分,这也意味着有性能问题的模块可能被忽略掉,这样的话,我们在设计性能测试案例时,应该采取一些策略和技巧,使用尽可能少的性能测试用例,发现尽可能多的bug。这方面内容我们将在本书的第10章中介绍。
  在具有软件测试共性的同时,性能测试也有自身的一些特点。
  1.性能测试不是功能测试
  性能测试不要求也无法做到覆盖软件所有的功能,通常我们只是对系统中某些功能或模块做性能测试。一般的,我们在选择性能测试案例时需要遵循以下的原则:
  (1)基本且常用的
  比如,一个E-mail系统,基本且常用的功能有注册、登录、收邮件、查询邮件,用户使用这些功能的频率较高,要做性能测试。而高级查询、过滤器、邮件列表等功能被使用的次数较少,可以不做性能测试,或者进行性能测试的优先级低一些。
  (2)对响应时间要求苛刻的
  这样的要求经常出现在金融和电信等对实时性要求比较高的系统中。比如,从手机呼叫开始,经过基站、核心网,再到被叫手机响铃,整个系统的处理时间应该在用户能接受的范围内。另外,一个负责和手机通信的基站在发生故障或掉电后,要能很快地恢复工作状态。这些功能都对时间有着严格的要求,一定要做性能测试,当然实际运作时,电信系统上线时所做的性能测试不仅于这些功能。
  将这些功能细分是性能测试中的事务(Transaction)。关于事务这个概念我们在后面的章节中将详细阐述。
  2.性能测试属于系统级测试
  从V型图可以看到,性能测试属于系统级测试。那么性能测试是基于单元测试、集成测试、功能测试等都已经完成的基础上,站在用户的角度去测试整个系统的。这包含两个含义:
  第一,性能测试是“两头在外”,软件性能需求不仅直接来自用户,终目的也是服务于用户。通过性能测试这个过程,从上面我们讲到用户的需求和性能测试指标的对应关系,可以看出。
  第二,性能测试开始的必要条件是软件系统已经处于一个比较稳定的状态,系统架构、主要代码、中间件等都不再有大的变化,否则会给性能测试带来很大的风险。
  思考
  基于以上事实,我们应该在软件流程什么阶段开始性能测试?结合自己的实际工作进行分析。
 1.2.2 性能测试策略揭秘
  谈到“策略”,这是如今很火、使用较多的一个词。不光在IT领域,其他各个行业中也都有各种各样的策略,如营销策略、风险规避策略等。策略即谋略、手段、方法,表现为权宜的行动路线、指导原则或过程。
  做事情讲策略,这是一种智慧,是人们聪明起来的表现,但当越来越多的策略“概念化”的时候,我们不得不去思考我们到底要达到什么样的目标,什么样的策略才是我们需要的。
  案例
  引用网上一位哲人说的话:“概念只是为了方便人们理解和研究世界万物事物而制造的工具,而终结果将使概念不再需要,如同庄子所说的得意而忘言”。语言是一种包装材料,它包装的是某种含义。因为人类传递信息必须使用语言,所以我们在研究的时候不得不借助于这种包装,但是当人的思维能力具备了打开包装直接取得内部的含义的时候,语言变得多余了。这时候再关注于语言和概念本身成了买椟还珠的现代版了。
  因此,我们应该关注的不是概念本身,而是概念背后的含义。理解了含义,再冠予它什么样的名词头衔,如“攻略“,对于我们都无关紧要了。而理解一个概念,我们可以靠WWH方法,即对概念的三个问题:Why、What、How。
  好,言归正传,回到软件性能测试策略中来。在性能测试过程中,只要有事情做,会有策略,如设计用例有设计策略,执行时有执行策略,调优时还有调优策略。为了不产生混淆,我们要说明的是,在本节中讨论的策略是性能测试设计策略。
  Why(为什么会有不同的策略)
  在软件性能一节中,我们看到软件的性能来自软件对空间和时间的综合方案,这种组合是很多的,因此用户的软件性能需求可能会多种多样。对于软件人员,我们做性能测试也要因地制宜,根据不同的性能需求,选择不同的测试策略。
  What(什么是性能测试设计策略)
  验证性能需求是测试目的,测试策略即已经被证明是行之有效的测试方法。
  How(怎样实施)
  常见的性能测试方法有以下几种:
  1.负载测试
  在这里,负载测试指的是常见的验证一般性能需求而进行的性能测试,在上面我们提到了用户常见的性能需求是“既要马儿跑,又要马儿少吃草”。因此负载测试主要是考察软件系统在既定负载下的性能表现。我们对负载测试可以有如下理解:
  (1)负载测试是站在用户的角度去观察在一定条件下软件系统的性能表现。
  (2)负载测试的预期结果是用户的性能需求得到满足。此指标一般体现为响应时间、交易容量、并发容量、资源使用率等。
  2.压力测试
  压力测试是为了考察系统在极端条件下的表现,极端条件可以是超负荷的交易量和并发用户数。注意,这个极端条件并不一定是用户的性能需求,可能要远远高于用户的性能需求。可以这样理解,压力测试和负载测试不同的是,压力测试的预期结果是系统出现问题,而我们要考察的是系统处理问题的方式。比如说,我们期待一个系统在面临压力的情况下能够保持稳定,处理速度可以变慢,但不能系统崩溃。因此,压力测试是能让我们识别系统的弱点和在极限负载下程序将如何运行。
  例子:负载测试关心的是用户规则和需求,压力测试关心的是软件系统本身。对于它们的区别,我们可以用华山论剑的例子来更加形象地描述一下。如果把郭靖看做被测试对象,那么压力测试像是郭靖和已经走火入魔的欧阳峰过招,欧阳锋蛮打乱来,毫无套路,尽可能地去打倒对方。郭靖要能应对住,并且不能丢进小命。而常规性能测试好比郭靖和黄药师、洪七公三人约定,只要郭靖能分别接两位高手一百招,郭靖算胜。至于三百招后哪怕郭靖会输掉那也不用管了。他只要能做到接下一百招,算通过。
  思考
  我们在做软件压力测试时,往往要增加比负载测试更多的并发用户和交易,这是为什么?
  3.并发测试
  验证系统的并发处理能力。一般是和服务器端建立大量的并发连接,通过客户端的响应时间和服务器端的性能监测情况来判断系统是否达到了既定的并发能力指标。负载测试往往会使用并发来创造负载,之所以把并发测试单独提出来,是因为并发测试往往涉及服务器的并发容量,以及多进程/多线程协调同步可能带来的问题。这是要特别注意,必须测试的。
  4.基准测试
  当软件系统中增加一个新的模块的时候,需要做基准测试,以判断新模块对整个软件系统的性能影响。按照基准测试的方法,需要打开/关闭新模块至少各做一次测试。关闭模块之前的系统各个性能指标记下来作为基准(Benchmark),然后与打开模块状态下的系统性能指标作比较,以判断模块对系统性能的影响。
  5.稳定性测试
  “路遥知马力”,在这里我们要说的是和性能测试有关的稳定性测试,即测试系统在一定负载下运行长时间后是否会发生问题。软件系统的有些问题是不能一下子暴露出来的,或者说是需要时间积累才能达到能够度量的程度。为什么会需要这样的测试呢?因为有些软件的问题只有在运行或一个星期甚至更长的时间才会暴露。这种问题一般是程序占用资源却不能及时释放而引起的。比如,内存泄漏问题是经过一段时间积累才会慢慢变得显著,在运行初期却很难检测出来;还有客户端和服务器在负载运行一段时间后,建立了大量的连接通路,却不能有效地复用或及时释放。
  6.可恢复测试
  测试系统能否快速地从错误状态中恢复到正常状态。比如,在一个配有负载均衡的系统中,主机承受了压力无法正常工作后,备份机是否能够快速地接管负载。可恢复测试通常结合压力测试一起来做。
  每种测试有其存在的空间和目的。当我们接手一个软件项目后,在有限的资源条件下,选择去做哪一种测试,这应该根据当前软件过程阶段和项目的本身特点来做选择。比如,在集成测试的时候要做基准测试,在软件产品每个发布点要做性能测试。