云计算服务 UI 性能测试的全自动化框架解决方案.docx
《云计算服务 UI 性能测试的全自动化框架解决方案.docx》由会员分享,可在线阅读,更多相关《云计算服务 UI 性能测试的全自动化框架解决方案.docx(18页珍藏版)》请在冰豆网上搜索。
云计算服务UI性能测试的全自动化框架解决方案
云计算服务UI性能测试的全自动化框架解决方案
简介:
性能是云计算产品极为关键的一个质量区域。
作者所在的项目IBMSmartCloudEnterprise(以下均简称SCE)是IBM云计算战略基于企业级的一款庞大而复杂的公有云产品,通过为用户提供可视化的网络平台接口,充分和快捷地帮助客户部署高灵活度的云方案。
一直以来,无论从股东,客户,合作伙伴还是产品各团队,交互端的性能始终都是一个重要的议题。
在过去的的半年里,产品的前端性能遇到了很大的挑战,提升用户体验之需求已迫在眉睫。
作为性能团队,亟待解决的任务是如何搭建一套综合的全面的自动化框架,不仅可获得交互端应用程序性能的详细数据,甚至还包括客户机服务器的资源监控,网络环境模拟,多参数融合控制等在内的一整套的集成化自动解决方案,从而为战略决策和技术调优提供第一手的真实的科学的数据。
这套解决方案不仅已应用于该项目本身,其设计思路,功能模块也适用于云工程领域的一般项目,并已在IBM云项目组里得到了一定程度的推广和使用。
无论您是架构师,还是性能测试或开发人员,如果您想部署一套UI性能测试的方案,阅读此文相信会有所裨益。
这套综合的解决方案至少包括以下优点和功能:
1.紧凑,灵活
2.可重用,易部署
3.易配置,方便而友好的用户界面
4.实现了互联网平台交互端的自动化驱动
5.实现了产品环境,测试环境以及多数据中心的覆盖和全兼容
6.实现了浏览器缓存控制,更充分的体现测试的归类
7.实现了网络带宽的模拟和控制
8.实现了多轮基准测试的控制,可以方便地定制集合级别的一次性调度
9.实现了客户测试端和产品服务器端资源数据的自动捕获和数据集成
10.实现了基准测试独一化、整合化输出的封装
11.实现了无论集合测试还是单一测试共用数据管道的输出统一
设计架构
没有直接相关的成功经验可以借鉴,从零开始搭建一套综合的多功能的满足需求的云工程交互端性能解决方案是一项任务更是一个挑战。
如何从专业而周密的角度做全局设计,我们面临诸多技术要素要去解决,例如
1.如何有效利用第三方引擎,设计、实现终端用户的自驱动和控制?
2.如何设计、实现一款合适的前端应用程序性能捕获工具?
3.如何设计、集成客户端服务器端系统数据的自动捕获和定向输出?
4.如何设计、实现公用数据管道的输出统一?
5.如何设计、实现基准测试独一化、整合化输出的封装?
6.如何设计、实现多轮基准测试的控制,可以方便地定制集合级别的一次性调度?
7.如何设计、实现网络带宽的模拟和控制?
8.如何设计友好的用户界面,简单易用,同时可配置多参数?
为便于您理解设计的脉络,以及内部模块之间的相互联系,我们给出此解决方案的整体开发架构图,如下图所示,
图1.总体开发架构图(查看大图)
由此架构图可以看出,整个框架是一个全面的端到端的自动化解决方案。
自动化测试程序部署在测试机(clienthosts),测试对象即产品服务部署在服务器(servers)。
方案一共包括两个独立的大功能模块,其中MainStream(baseline)顾名思义是基准测试,MainStream(run2run)则是多轮基准测试,如果把基准测试作为一个单元,那么run2run可以理解为可定制的重复单元测试集合。
基准测试和多轮基准测试的实现本身都是互相独立的,区别在于后者调用了前者并重点在于调度控制。
基准测试是非常重要的,可以看到除多轮测试的虚线框之外的绝大部分都是在描述基准测试的设计和工作方式。
测试的执行者只需要编辑好properties文本文件,通过这个唯一的接口传达给主程序必要的配置信息,剩下的就是程序自己全权运行了。
那么程序本身究竟融合了哪些功能模块呢?
∙clientcapturing是主程序自动捕获测试端的系统信息,比如在测试运行过程中CPU的数据,以及对此测试配置文件baseline.properties的拷贝。
∙Network/Servercapturing是程序自动触发和捕获从测试端到产品服务器端之间的网络时延,以及IP路由数据。
∙除此之外,程序一开始就会根据配置文件的信息去实施带宽控制,在图中叫做AutomatedBandwidthControlModel,是否开启此功能以及如果开启的话上行和下载速率分别是多少均可以在properties中设置键值进行精确控制。
∙既然是UI的测试,必然需要触发UI操作,在图中叫做WebDriver,我们基于AutoIT的IE.au3库作为web引擎写了完整的代码来控制页面操作。
可以看到项目中我们一共关注了6个页面,分别是Home,Login,ControlPanel,Account,Overview,Logout。
∙在触发和访问每个页面的时候并不是简单的点击操作,这就是为什么我们叫做”IntelligentTimingControlModel”。
如果此页面无法访问或者由于其他原因导致页面元素无法触发,我们统一定义为Error;如果该页面已经触发但是长久没有结束全载,我们定义为Timeout;如果成功触发并成功全载,我们成为Success。
无论Timeout还是Error,程序都会走向消亡处理,比如逐步关闭CPU的采集,关闭带宽的模拟,输出相应日志,关闭IE,主程序退出。
只有在Success的情况下,主程序才会继续前行,当且仅当最后访问的Logout也是Success的状态,才会输出标记此基准测试为Success的日志,并消亡整个程序。
∙刚才谈到了日志,我们有必要再次细解。
从图中可以看到伴随每个基准测试都有两种日志生成。
”uniquecombinedsinglebaselinedataset”是包含一次基准测试的所有详细数据,它是独有的按照时间戳命名的文件夹。
“uniqueformattedloginsharedbed”是将任何一次基准测试都简要记录在案的一个自动生成的共享文件,只要有基准测试进行过,就会有对应该测试的摘要性日志作为一行而生成,并且该文件被所有的测试共享,我们定义了其统一的格式,这个格式请见正文部分之”公用数据管道输出统一”。
多轮基准测试是我们提到的对基准测试的调度控制。
如果我们把每个基准测试叫做session的话,多轮基准控制就称作sessioncontrol。
用户可以通过编辑properties配置文件来设置自己想要跑出几轮成功的基准测试,并且设定最大的允跑轮数。
因为多轮基准是对基准的调度,所以一切在基准测试中所提到的环节,包括操控和日志等等所有的一切都不会被改变,一切都会井然有序的运作。
回页首
解决之道
这一部分,我们将按如下主题为序进行逐一讲解,
∙终端自驱动和控制
∙应用程序性能捕获
∙系统数据捕获与定向输出
∙公用数据管道输出统一
∙基准测试独立整合封装
∙多轮基准测试控制与调度
∙网络带宽模拟与控制
∙用户界面多参数配置
终端自驱动和控制
终端自驱动和控制其实就是实现针对需求的界面自动化和控制,这也是UI性能测试的必要条件。
实现这一要求就是实现一个驱动引擎。
可以基于企业级的工具平台,如RationalFunctionalTester、QuickTestProfessional,亦可以使用开源第三方工具或者类库,如Selenium,waitR,waitN,AutoIT,进行上层二次开发,进而搭建个性化的自动化驱动平台。
具体到本方案,我们优先考虑了AutoIT,因为主框架中会有一些与Windows平台对象的交互,而这方面AutoIT有丰富而稳定的接口。
其次,其优势虽在交互端自动化功能一般,但其提供了专门控制IE浏览器行为的IE.au3类库接口,足够应付我们的项目需求。
综合上述,基于AutoIT在桌面和系统级都有良好的支持,我们的主框架代码将基于此来实现。
为了进一步说明自动化的内涵,这里将共享一段完整的代码片段来说明终端自驱动和控制,此片段完成的功能可以大概表述如下:
触发IE浏览器,访问SCE起始页面,之后寻找并触发IE浏览器上的pagetest开关,回到页面域判断是否需要处理httpscertification,接着等待页面全载,巧妙通过判断pagetesttab数目判断页面是否完成全载,如果全载则输出文本性能数据,关闭pagetest,进入下一个页面处理阶段;如果在规定的3分钟内没有成功,则认定为Timeout,进入程序消亡过程(详情如架构图总论所述);如果触发pagetest开关之后都没有机会处理certification,那么程序认定此页面为Error,进入程序消亡过程。
后续5个页面的处理机制将与此雷同,故不再赘述于此。
清单1.终端自驱动与控制-Home访问处理实例
;浏览器对象初始化,激活,等待
$oIE=_IECreate("about:
blank")
WinActivate("[CLASS:
IEFrame]","")
WinSetState("[CLASS:
IEFrame]","",@SW_MAXIMIZE)
WinWaitActive("[CLASS:
IEFrame]")
Sleep(5000)
;pagetest插件对象初始化和捕获
$hToolbar=ControlGetHandle("[CLASS:
IEFrame]","",
"[CLASS:
ToolbarWindow32;INSTANCE:
1]")
;--开始Home页面访问和处理--
;判定不同的测试环境,处理httpscertification问题,达到访问同一化
If0_GUICtrlToolbar_ClickButton($hToolbar,$BtnCmdID,"left",True)
Sleep(2000)
_IENavigate($oIE,$URL,0)
Else
_IENavigate($oIE,$URL)
$oSSL=_IEGetObjByName($oIE,"overridelink")
If$oSSL==0Then
;将状态置为Error
$status="Error"
;重置本机网络带宽为默认值
ResetBW()
;停止perfmon,并将CPU数据拷贝至本轮基准测试所创建的输出所在
Run(@ComSpec&"/c"&'logmanstoptest',"",@SW_HIDE,$STDERR_CHILD+$STDOUT_CHILD)
FileCopy("C:
\PerfLogs\cpu.tsv",$configDir&"\*.*")
;计算总输出
$output=$runId&"|"&$env&"|"&$USER&\
"|"&$baselineName&"|"&$status&\
"|"&$CCcomment&"|"&$BWcomment&"|"&\
$comment&"|"
;将该输出写入execution.log
loging($logFile,$output)
AppendResponse2Log()
loging2line($sessionFile,$Indicator&$status,1)
loging2line($sessionFile,$Target&$baselineName,2)
;截屏并存为图片,存贮到本轮基准测试所创建的输出所在
Sleep(5000)
$hBmp=_ScreenCapture_Capture("")
Sleep(500)
_ScreenCapture_SaveImage($rDir&"\Screen_home_error.jpg",$hBmp)
_IEQuit($oIE)
Exit
EndIf
;触发pagetest
_GUICtrlToolbar_ClickButton($hToolbar,$BtnCmdID,"left",True)
Sleep(2000)
;绕过certification
_IEAction($oSSL,"click")
EndIf
;通过检测pagetest的tab控件数量来判定是否结束页面的捕获,并处理Timeout情况
$hPagetestTabs=ControlGetHandle("AOLPagetest","",\
"[CLASS:
SysTabControl32;INSTANCE:
1]")
If$hPagetestTabs==""Then
Exit
EndIf
$i=0
While1<>_GUICtrlTab_FindTab($hPagetestTabs,"Checklist")
Sleep(500)
$i=$i+1
If$i==360Then
;将状态置为Timeout
$status="Timeout"
;重置本机网络带宽为默认值
ResetBW()
;停止perfmon,并将CPU数据拷贝至本轮基准测试所创建的输出所在
Run(@ComSpec&"/c"&'logmanstoptest',"",@SW_HIDE,$STDERR_CHILD+$STDOUT_CHILD)
FileCopy("C:
\PerfLogs\cpu.tsv",$configDir&"\*.*")
;计算总输出
$output=$runId&"|"&$env&"|"&$USER&\
"|"&$baselineName&"|"&$status&"|"&\
$CCcomment&"|"&$BWcomment&"|"&\
$comment&"|"
;将该输出写入execution.log
loging($logFile,$output)
AppendResponse2Log()
loging2line($sessionFile,$Indicator&$status,1)
loging2line($sessionFile,$Target&$baselineName,2)
;截屏并存为图片,存贮到本轮基准测试所创建的输出所在
$hBmp=_ScreenCapture_Capture("")
Sleep(500)
_ScreenCapture_SaveImage($rDir&"\Screen_home_timeout.jpg",$hBmp)
_IEQuit($oIE)
Exit
ExitLoop
EndIf
WEnd
;强制前端化显示pagetest
WinActivate("AOLPagetest","")
WinWaitActive("AOLPagetest")
Sleep(1500)
;调用ptExport将pagetest的详尽数据和优化策略进行保存,输出到基准测试输出所在
ptExport("home")
;关闭pagetest
WinClose("AOLPagetest","")
应用程序性能捕获
应用程序的性能捕获,从本质上来讲就是获得所有页面活动的性能数据,具体到每一个请求量级。
我们考虑两点要素:
第一要轻量级,不引入额外性能噪音;其次要有丰实的数据,达到我们的基本要求。
调研发现可以借助YSlow、pagetest,、dynatrace等作为应用程序前端性能的捕捉引擎。
pagetest数据丰富,详实有效,支持文本和图形化,可以满足我们的数据要求;其在浏览器上作为插件存在,轻量级,且便于被控制。
基于这两大优点,我们的主代码将会实现与pagetest的全方位交互,包括节奏判定,输出控制以及各集成调用。
便于读者直观上对pagetest的界面有所了解,示图如下,
图2.pagetest界面示例(查看大图)
因为代码的强耦合,无法剥离独立的片段来专门解释。
能够表征这一节要义的代码片段在上一小节”终端自驱动和控制”中已经全被包括,可以了解pagetest于何时、何种条件下,被触发、被操控、被关闭,以及如何被巧妙用作全载动态智能判断的方法。
系统数据捕获与定向输出
系统数据涉及到测试机、服务器相关系统数据。
我们的解决方案希望集合各类数据,以提供足够完备的调优支持。
比如现阶段我们对测试机的CPU使用、网络延时、IP路由等感兴趣,我们需要实现主代码自动获取这些数据的可能性。
从策略上讲,CPU数据可以通过自动触发perfmon获得,网络延迟数据可以通过即时ping重定向获得,路由数据可以通过初始化tracert重定向获得。
图3,4,5分别是给出一个直观印象。
但我们要重申的是,这不是我们要的结果。
我们所谓的数据捕获是基于代码的自动实现以及自动定向输出,即通过AutoIT主代码中调用Dos命令,并且获得该调用的进程句柄,从而访问其子进程IO管道拿到文本数据信息。
图3.perfmon交互
上图是perfmon的界面示意,在主程序中,我们是这样交互perfmon的:
在每个基准测试里,程序进入webdriver之前强制停止perfmon数据搜集动作,并强制删除已有的旧数据:
;stopcpuandremovecpuandstartperfmon
Run(@ComSpec&"/c"&'logmanstoptest',"",@SW_HIDE,$STDERR_CHILD+$STDOUT_CHILD)
FileDelete("C:
\PerfLogs\cpu.tsv")
Run(@ComSpec&"/c"&'logmanstarttest',"",@SW_HIDE,$STDERR_CHILD+$STDOUT_CHILD)
无论任何一个页面有异常出现(Error、Timeout)或者整个基准测试全程无异常成功完成时,均调用Dos命令停止perfmon,并且拷贝由其产生的CPU数据:
;stopperfmon©filetosys_metric
Run(@ComSpec&"/c"&'logmanstoptest',"",@SW_HIDE,$STDERR_CHILD+$STDOUT_CHILD)
FileCopy("C:
\PerfLogs\cpu.tsv",$configDir&"\*.*")
图4.DosPing
上图是Dosping的界面示意,在主程序中通过调用Dos命令,获得该调用的进程句柄,从而访问其子进程IO管道拿到文本数据信息。
也就是说通过下述方法,在基准测试的sys_metrics文件夹里将自动生成ping.log,文件内容为上图红色所框注的内容一致。
下面代码详细说明了这个过程。
清单2.网络延迟数据捕获与定向输出
;自动创建sys_metrics文件夹,ping.log文件作为此次基准测试的定向输出所在
$configDir=$rDir&"\sys_metrics"
$networkFile=$configDir&"\ping.log"
DirCreate($configDir)
;获取延迟数据并定向输出
$network=getLatency($ADDRESS)
loging($networkFile,$network)
;函数getLatency()实现-获取延迟数据
FuncgetLatency($address)
Local$mycmdline='ping'&$address
Local$foo=Run(@ComSpec&"/c"&$mycmdline,"",
@SW_HIDE,$STDERR_CHILD+$STDOUT_CHILD);
Local$line2=""
While1
$line=StdoutRead($foo)
$line2=$line2&$line
If@errorThen
ExitLoop
EndIf
Wend
Return$line2
EndFunc
;函数loging()实现–定向输出
Funcloging($fileName,$info)
Local$file
$file=FileOpen($fileName,1)
If$file=-1Then
MsgBox(0,"Error","Unabletoopenfile.")
Exit
EndIf
FileWriteLine($file,$info)
FileClose($file)
EndFunc
图5.Dostracert
上图是Dostracert的界面示意,其代码处理原理与ping一致,唯一只是将ping替换为tracert。
不再赘述。
公用数据管道输出统一
提出公用数据管道是基于一个需求:
针对每一轮基准测试,我们都需要一个综合性输出,而且此输出有一致的格式,并且被基准测试共享。
无论是什么样的基准测试,比如有时您可能叠加了带宽控制,可能您施加了缓存管理,在这里,公用数据管道都是通用的。
便于直观,我们设计了统一的文件规范,每一行对应一个单元测试输出,并附样式如下
4000030||stagenv_40@|
D:
\pagetest\Base_01-24-2011-16-51-55_N|Success|CleanCache[false]|
BW[(false)()()]|N/A|Home,25.254second,Login,23.036second,
Account,7.938second,Control_Panel,18.019second,
Overview,7.210second,Logout,5.085second|
注:
自左到右依次是独立标识、web对象地址、用户、单元统一化集成输出存储位、测试结果标