9、 经验在本次性能测试的过程中,我们遇到一些问题,通过解决这些问题,从中获得了一些经验。
现总结如下: 问题一在我们对系统进行测试的过程中,某些操作是相关联的。例如我们测试“查看客户资产历史”这个交易的系统响应时间,这时需要先列出客户的基本信息,选中一个客户,点击打开另一个页面,才能查看到该客户的资产历史信息,同时,在测试脚本中需要对所选择的客户编号做一个参数化,但由于LoadRunner不提供像WinRunner或QTP一样识别页面对象的功能,如果在Vugen中直接抓取页面上显示的客户编号去参数化,实现起来将十分烦琐。考虑到在以上那两步操作中,第一步“列出客户基本信息”只是辅助的操作,而第二步操作“查看客户资产历史”才是我们要测试的功能点,因此我们忽略了这二者之间的关联性,仅对第二步操作中的客户编号进行参数化。(只要服务器端对此不加验证,甚至我们将第一步操作都忽略掉,也是可行的)。结论:LoadRunner的工作原理是根据所选择的协议组装成相应的报文在前后台之间通讯,以此达到模拟实际操作的目的,因此我们只需将要测试的交易或功能点所需要组装的报文传送给后台服务器即可(因为我们关注的只是系统的性能,不是功能),而不必像功能测试那样,按部就班地重现每一步操作。
问题二在测试过程中,我们发现有一个查询交易的系统响应速度特别慢,无论是在Controller中使用单个虚拟用户执行脚本,还是在Vuser中直接运行,情况均是如此,然而当我们用手工进行同样操作的时候,响应时间却明显地小于工具统计出来的时间,也就是说,在LoadRunner中模拟操作的结果与真实操作的结果明显不一致。经过反复尝试与观察,我们才终于找到问题的原因所在:该查询交易是通过客户的证件号码查询客户信息,当用户输入客户的证件号码时,如果没有选择证件类型,系统会自动将证件类型设置为默认值“身份证”。按“证件类型+证件号码”为组合索引查询客户信息表,查询速度极快,而在我们录制脚本时,忽视了“证件类型”这项输入,只有“证件号码”,因此查询的效率大为降低。解决办法:只需在测试脚本中,对CertType(“证件类型”)一项赋值为“A”(“身份证”),此时在LoadRunner中重新运行该脚本,响应速度提高,统计结果与实际完全一致!结论:LoadRunner的工作原理是根据所选择的协议组装成相应的报文在前后台之间通讯,以此达到模拟实际操作的目的,因此我们在测试脚本中组装发送到服务器端的报文时,注意一定要和实际操作时的发送报文完全一致,这样才能保证测试的结果与真实情况相吻合。这就要求在测试正式开始执行时,要对测试脚本进行反复的调试,通常的做法是:在Vugen中执行一遍脚本,统计执行某个事务的时间,再用手工实际做一遍同样的操作,大体上比较一下,确保与实际估算的时间没有太大出入后,再逐渐增加并发用户数,正式开始性能测试。
问题三在我们的每个测试脚本中的init部分,都录制了登录系统的操作,并且对登录的用户名进行了参数化,使用各种不同身份的用户(分行主管、支行主管、客户经理等)进行相同的操作。在并发测试过程中发现对某些查询交易测试的结果波动较大,系统响应时间从零点几秒到几十秒不等。经检查后发现原因在于:使用不同身份的用户登录系统后,在输入查询条件后,点击查询按钮后会将根据该用户的身份,将其所属的分行机构号、支行机构号、客户经理编号等一并提交,因此在脚本中,就必须根据不同的用户身份,分别将其对应的分支行机构号等也运用参数提交,否则在执行脚本时就会出现查询不到记录或查询速度变慢等各种问题。解决方法有三个:1、修改脚本,使其能够依据用户的身份分别传送相应参数,2、针对不同类型的用户使用不同的脚本分别测试。3、输入参数使用统一的用户类型。在实际中,我们为了简化脚本的复杂度,节省对脚本编程的时间,采取的是第三种方法。结论:由于LoadRunner的工作原理是根据所选择的协议组装成相应的报文在前后台之间通讯,因此它会跳过在应用程序前台进行的校验,所以在脚本回放的时候一定要注意在脚本中提前进行这些校验或改由人工控制,以保证发送报文的正确性(如操作权限的控制等)。
问题四测试多用户并发登录系统的时候,从虚拟用户图和事务图上发现,总有一部分用户在登录的时候要等待很长时间,用户登录的最小时间与最大时间相差非常大。于是我们在让脚本自动运行的同时,手工再登录一个用户,发现无论如何都不会发生等待的情况,多次试验的结果均是如此,也就是说LoadRunner测试的结果与实际结果再次发生了偏差!经过反复的调试,以及与程序开发人员沟通,我们终于发现问题的原因所在:在用户登录系统的时候,系统会自动记录登录用户的信息,并产生一个登录ID,以此ID做为主键,向数据库插入记录。因此当大量用户在极短的时间内同时登录时,就有可能出现生成相同的登录ID的情况,此时便会造成数据库中的主键冲突,导致用户等待很长时间或登录失败。而我们手工测试时却无法做到在很短的时间内同时登录,因此很难用手工重现此种情况。通过LoadRunner的模拟表现出来的状况,正是我们测试出程序存在的性能问题,并非与实际结果的偏差。还有一个例子,在第二轮性能测试中,同样发生了类似的情况。在本系统中,如果同一个用户登录后,未正常退出超过5次,系统将会把该用户锁住,使其无法再次登录,而我们用于参数化的用户名个数有限,因此当脚本使用大量用户同时登录时,很容易造成同样的用户登录系统而未签退的情况发生(脚本正在执行,还未能退出),此时将会造成许多用户操作的失败。结论:使用LoadRunner可以模拟出大量用户同时对系统操作的情况,而这些情况通过手工往往是很难重现出来的。例如大量用户在同时对系统做某些操作时,很容易造成数据库的死锁、锁等待、主键冲突、数据混乱等等问题,因此在做性能测试的同时,也常常可以连带测试出系统的一些隐蔽的“缺陷”。在本次性能测试中,这种例子是很多的。对待此类“缺陷”,应具体情况具体分析。有些确实是程序的BUG,需要修正,而有些可能只是很极端的情况,只有在做压力测试时才有可能发生,可不必深究。
问题五此问题发生在第二轮测试(即回归测试)中。在第一轮测试中发现的性能问题,经程序员修正后,我们对系统进行了第二轮性能测试,以验证其性能改进的效果。在前一轮测试中,我们发现通过选择客户级别为“未评级”时,查询的速度极慢,经过改进后,速度应有较大提高。然而在回归测试中,却依然很慢。经过对测试脚本和程序的仔细检查,才发现原来在程序中已将“未评级”这个选项去除,而我们的测试脚本的参数文件中仍然保留有该选项,因此测试的结果与前次没有区别。在参数文件中将该选项去掉后,测试结果正常,查询效率有所提高。