运行测试

  下面我们将简单讨论需要运行哪些测试以及何时运行它们。

  运行哪些测试

  所有频繁进行的用户操作都应该有对应的测试。这些测试应该记录吞吐量、错误率和响应时间的统计数据。然后你还应该复用这些测试,从而构成更复杂的测试。所有这些测试应该一起执行,尽可能地模拟真实情况,这样你能从中获悉产品的性能状况。

  准备好这些测试以后,可以在不同的用户量、不同的数据规模下运行它们,观察性能数据的伸缩情况。如果可能的话,还应该在不同的机器数量下进行测试,从而了解硬件能给性能带来多大提升。从这几个方面,你能获知产品的伸缩能力。

  后,你还应该在超负荷的情况下进行测试,从而找出系统的失败点。还应该在用户分布情况下基本不变的前提下加快用户操作速度进行测试。此外长时间运行性能测试有助于了解系统的可靠性。

  何时运行测试

  答案显然是越频繁越好。但显然这里有个问题,性能测试的本质决定了运行它们需要很长时间。尤其是可靠性测试,只有运行的时间足够长才有意义。所以不太可能为所有的构建都运行全套性能测试。我们既希望开发者提供快速的反馈,又希望对系统进行全面的测试。

  一个解决办法是找一台专门的机器,为新的构建执行一组有限的性能测试。如果测试结果明显有别于前一构建,本构建应该被视为失败。从中得到的结果虽不能代表系统的真实性能,但可以作为一个早期预警系统,让开发者们能很快知道自己的工作是否严重影响了产品的性能。

  整套的性能测试应该尽可能频繁地在完整的性能环境下运行,可能每天运行几次。如果对环境的访问受到限制,在晚上执行性能测试也是个不错的折衷办法。

  可靠性测试显然需要更长的时间,而且通常必须与其他性能测试运行在同样的环境下,也是说没办法在工作日里进行。所以如果没办法找到一个专门用于可靠性测试的环境,在每个运行可靠性测试也是个解决办法。

  在何处运行测试

  如果可能的话,应该尽量让性能测试环境模拟真实的生产环境。如果生产环境太过庞大而无法整体模拟,那么应该让性能测试环境模拟生产环境的一个部分,然后将真实的性能需求等比压缩到性能测试环境的水平。

  如果无法得到专用的性能测试环境,事情会变得比较棘手。如果必须和功能测试团队共享环境,那么可以考虑在夜里执行性能测试。此时,好针对性能测试和功能测试使用不同的数据库,并用脚本来切换数据库,这样两组互不相容的测试不会互相干扰。当然,这样做的前提是你能够在台式机上运行你的应用程序并编写性能测试。

  在夜间运行测试需要注意,此时的网络情况常会与平时有所不同中。网络可能不像白天那么繁忙,因为人们没有在工作;但也有可能数据备份或是别的批处理任务被放在晚上进行,因此占用大量的网络流量。如果在性能测试的过程中突发大量网络活动,测试结果有可能受到明显的影响,以至于你看不出这种影响的存在,除非换个时间来运行测试。为此,应该安排在正常工作时间也运行一次性能测试,这样你才知道运行测试的时机是否是对结果明显影响的原因。如果不同时间运行测试的结果有很大差异,那么你可以尝试模拟正常工作时间的平均网络流量,或者看这种结果差异是否保持一致,如果差异始终一致,在查看结果时将其考虑在内即可。

  根据我的经验,如果对测试环境存在明显的争用现象,很有必要对其加以管理,谁在什么时候使用系统,使用哪个数据库,都应该事先规划好。有时测试环境下运行的测试会失败,在本地机器上却能通过。这时需要把环境切换到性能测试的数据库,在问题修复之前其他QA都不能使用该环境。由于共享一个测试环境会限制运行性能测试的频度这一客观困难的存在,我们应该尽量尝试用一个单独的环境来运行性能测试,即便这个环境配置与生产环境不很相似也没有关系。

  假如你面前摆着两个选择:一个测试环境与生产环境差异较大;另一个测试环境很接近生产环境,但只能在有限的时间使用。你会怎么选,正确答案是两个都要。你可以在独占的环境里编写性能测试,并且不受阻碍地频繁运行它们,这样你可以把这组测试加入到持续集成系统中。接近生产配置的测试环境是一个有价值的参与,你可以将其中得到的测试结果与从日常频繁运行的非生产系统中得到的测试结果相对比,从而了解这些测试结果与系统的终性能究竟有何关系。

  较小测试设备上的测试结果与生产环境的性能有何关系。

  一个常见的问题是测试环境的配置和生产环境不同。必须知道,如果测试环境和生产环境毫无相似之外,那么也无法判断硬件可系统性能的影响。所以,如果不得不用一个较小的环境来做性能测试,应该怎么做?我的建议是模拟生产系统的有代表性的部分。下面我将介绍具体的做法:

  以一个大容量的WEB应用程序为例。系统的基本架构可能包括几台应用程序服务器、几台WEB服务器和几台数据库服务器。假设生产系统有N台数据库服务器(都是高配置的机器)、2XN台应用程序服务器(配置较高)和4XN台WEB服务器(配置较差),那么你可以考虑我的办法:准备一台数据库服务器,其性能大约是生产数据库服务器的一半;准备一台应用程序服务器,其配置和生产环境的应用程序服务器一样;再准备一台WEB服务器。

  现在你拥有了一个应用程序服务器与数据库服务器的组合,两者之间的相对性能比与生产环境一致,性能值则大概降低了一半上,并且WEB服务器的配置也不足。

  在这个环境下,你可以直接访问应用程序服务器,借此了解应用程序的性能,从而掌握一台应用程序服务器所能达到的性能水平。然后你可以通过WEB服务器来访问,并且选择一种让WEB服务器成为瓶颈的测试场景,于是你可以掌握一台WEB服务器所能达到的性能水平,而不会受到应用程序的影响。根据这两组数据,你应该能比较准确地判断在生产环境下各种服务的配比是否合适,并且对抱有一定程序信心的生产系统的性能有所预估。

  需要记住的是由于每个WEB请求只能由一个应用程序服务器/数据库服务器的组合来处理,因此当服务器数量增加时,只有吞吐量的提升是能够确定的。而响应时间只会因为每台服务器的CPU计算能力或者内存增加而提升-假设系统负载水平保持不变的话。其原因在于,更快的CPU能以更快的速度处理更多请求,而更多的内存则让更多的信息得以缓存。

  当然,以上讨论都基于一系列假设:机器配置始终保持不变,CPU都是同一家厂商制造的,操作系统都一样,数据库/WEB服务器/应用程序服务器的组合也保持不变。

  请时刻牢记,测试环境与生产环境在机器配置、软件等方面差异越大,对真实系统的性能估计越不准确。在前面的例子中,你可以把测试环境看作生产环境的一部分,从中估算出的生产环境性能不会谬不千里。如果机器的配置与生产环境毫无可比性,用的软件也全然不同,(例如把Oracle改为MySql, 把JBoss改为WebSphere),你仍然可以用这个环境来度量性能的变化情况,但根据测试结果估算出的生产环境性能数据将非常可疑。

  应该用多大规模的数据库的做性能测试

  在做性能测试时必须记住,数据库的规模会显着影响从表中取出记录所需的时间。如果一张表没有合适的索引,当数据规模较小时可能还看不出问题;然而,一旦有几千行以上的生产数据,性能会严重降低。

  应该先与关注性能的客户交流,争取拿到一份生产数据库的副本,这样可以针对它来进行测试。在这个过程中要注意数据保护,并对拿到的数据库做适当的清理,删除或修改其中的私密信息。

  你还应该与客户探讨数据规模发生变化的可能性。数据量会大致保持在现有水平上吗?还是很可能会增长?如果会增长,增长的速度会有多快?只有了解这些信息,你才知道是否应该用一个比现在大得多的数据库来做性能。

  要得到一个更大的数据库,好的办法是使用稳定性测试创建新的数据库。在稳定性测试中,你应该会创建新的用户和新的交易数据。如果这组测试整个都在顺利运行,那么你能得到一个适用于未来情形的数据规模了。

  如果处理第三方接口

  如果系统用到很多第三方接口,性能测试好不要直接去使用这些第三方系统。原因有两点:首先,第三方系统可能并不适合成为性能测试的一部分;其次,即使第三方系统提供了测试环境,依赖你无法控制的第三方系统会降低测试的可靠性。

  好的办法是用一个单独的测试来获知第三方系统的平均响应时间,然后为它写一个mock或者stub,直接等待那么长的一段时间然后返回一个固定的响应。当然也可以直接返回响应,不过这样会让测试失去了一些真实性,因为没有了等待第三方系统的时间,应用程序服务器能够更快地释放数据库连接或者网络连接,这会给终的测试结果造成差异。

  需要多少种测试案例

  这是个重要的问题,因为不恰当(过多或过少)的测试会严歪曲测试结果。如果测试案例太少,所有相关的信息都会被缓存起来,系统会显得比实际情况更快,如果测试案例太多,缓存会溢出,系统会显得比实际情况要慢。

  多少种测试案例才是合适的呢?你需要和关注性能的客户讨论系统的预期使用情况,并且如果可能的话,请分析现有系统的使用日志从而找到一个答案。比如说,如果要测试的场景是“从应用程序获取顾客信息”,那么要在测试中覆盖到的顾客数显然和正常操作中涉及的顾客数有关。如果正常情况下系统中每天有5%的顾客信息记录会被取出,那么你的测试也应该覆盖这么多的顾客。