Sikuli: GUI性能测试

在GUI自动化测试中,除了功能测试,UI性能测试也是很重要的一块;毕竟,没有一个用户喜欢反应迟钝的图形界面。那么,在Sikuli中应该如何编写性能测试脚本来测试UI响应时间呢?

最直接的方法,当然是写wait语句,同时在wait语句的上下进行计时:

import time

startTime = time.time()  
wait('a_screenshot_here')  
endTime = time.time()  
#STcommon is my customized module
STcommon.log('Test Case 1 Time: ' + (endTime - startTime))  

但是很多情况下,上述写法将导致FindFailed异常 — Sikuli中默认wait方法的timeout值是3秒,一旦在3秒内预期的图形元素并未出现,wait语句就会报错(FindFailed)。

为了解决这个问题,我们可以简单的在wait语句中输入一个保险的timeout值(单位为秒):

import time

startTime = time.time()  
wait('a_screenshot_here',100)  
endTime = time.time()  
STcommon.log('Test Case 1 Time: ' + (endTime - startTime))  

看上去这样的代码没什么问题。其实不然,使用上述代码进行测试之后会发现,有时候得到的数据与手工掐秒表得到的数据相比,会偏大。尤其是对于本地应用软件或者C/S架构客户端中响应时间较长的Test Case而言,测试数据会严重偏大,这又是为什么呢?

原来,在Sikuli中,wait语句会不断地扫描当前屏幕来试图识别相应的图形元素,这样就会占用当前系统的资源 — 长时间运行wait将占用大量的系统资源,从而影响其他应用程序的运行。

谨慎的使用wait,同时谨慎的使用wait函数的参数。

如果我们就是需要测试那些响应时间较长的Test Case该怎么办呢?该如何来降低Sikuli这一测试工具对于待测对象的影响呢?

一种简单的方式是预估一个较小的响应值,在这个预估值的基础上调用wait来进行测试:

import time

startTime = time.time()  
sleep(12) #sleep function will not cost system resource  
wait('a_screenshot_here')  
endTime = time.time()  

这种方式有比较大的局限性:仅适用于响应时间变化不大的Test Case;对于响应时间变化较大的Case,使用这种写法将导致比较大的误差,同时也引入了发生FindFailed异常的风险。

更好的方式是重新定义扫描屏幕的时间间隔:

import time

startTime = time.time()  
while True:  
    if exists('a_screenshot_here'):
        break
    else:
        sleep(3)
        continue
endTime = time.time()  

这种写法也并不是完美的:首先,它引入了更多的误差(误差最大值就是手工设置的时间间隔)。其次,手工设置的时间间隔到底应该是多少,取决于经验 — 间隔过长,引入的误差就过大;而间隔过短,Sikuli对于待测试系统的影响就会过高。

在经过一段时间的探索之后,我认为最佳的解决方案是这样的:

  1. 在Sikuli中使用wait语句(有自定义的timeout值)来不断扫描待测试系统的GUI,这样可以去除由于编码本身所引入的误差。
  2. 让待测试系统运行在另一台远程机器上。
  3. 借助远程桌面软件,让Sikuli在本地机器的远程桌面窗口中操作待测试系统。Sikuli也可以直接在远程桌面的窗口中启动待测试系统

这样一来,既没有人为引入的误差,待测试系统也不会受Sikuli占用计算资源的影响。唯一需要满足的条件是:本地机器与远程机器之间的网络通信必须比较通畅;也就是说,本地机器必须能够比较流畅地操作远程桌面。

Chuan Shao

Read more posts by this author.

Shanghai

Subscribe to Chuan's blog

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!