lsekfe 发表于 2016-9-13 11:18:35

一个基于.NET平台的自动化/压力测试系统设计简述

转自:博客园
AutoTest系统设计概述AutoTest是一个基于.NET平台实现的自动化/压力测试的系统,可独立运行于windows平台下,支持分布式部署,不需要其他配置或编译器的支持。(本质是一个基于协议的测试工具),前面还有一篇对其功能的简单介绍【AutoTest简介】AutoTest用于发布的部分有2个部分,主程序【AutoTest.exe】及分布式部署程序【RemoteService.exe】(用于将将测试业务分布式部署到远程主机)而在内部又被设计为多个组成部分,最终完成对自定义脚本文件的解析并按脚本要求的模式去执行。http://images2015.cnblogs.com/blog/209007/201509/209007-20150916163158633-489760944.png
如上图,简单介绍下执行逻辑层主要由3部分组成
[*]MyControl.dll                     该部分主要为表示层提供专门为业务定制的UI控件等用于显示数据的组件
[*]myCommonTool.dll                  该部分为这个解决方案即这个系统提供通用的工具方法及组件如日志系统(指系统本身的日子系统,测试过程中的日志或记录由专门的记录采集模块完成)
[*]CaseExecutiveActuator.dll       该部分为这个测试平台提供最核心的逻辑处理部分,如脚本的解析,脚本的选择,脚本的执行等(对于系统来说添加任意的其他的协议支持也仅需要修改这个库中的部分内容)

表示层暂时是由2部分组成
[*]AutoTest.exe                            测试平台显示界面,运行于windows环境下,赋值数据及结果的呈现,同时负责与操作者者进行交换
[*]RemoteService.exe                  分布式部署程序,负责在远程主机开启服务实现测试任务的分布式部署,分布式远程服务基于WCF框架理论上支持跨internet的分布式部署

最下面的2个模块是用于系统内部模块的单元测试,本身与系统运行无关,所以就不赘述了
此外还有一个重要的组成部分-脚本文件,这里使用的脚本依托于XML文件,规则上基本是独立定义的。脚本文件控制所有Case的执行方式,内容,甚至是执行路径,还包括对断言的额外处理。脚本文件被解释器(CaseExecutiveActuator的一部分)转换为系统/工具直接可以使用的数据结构,并最终被执行。(脚本规则相对独立,将不会在此篇中涉及)
核心执行模块【CaseExecutiveActuator】
CaseExecutiveActuator模块主要由2部分组成,脚本处理部分(算法)及脚本内容的存储部分(数据)。脚本对外的存在形式是XML文件,这个XML也是最终的脚本文件。系统解析这个XML文件(对CASE内容,或测试业务的修改包括新建也只是对XML脚本文件的修改而),然后对其进行进一步处理(当然使用合适的数据结构对其进行存储是第一步)。脚本的存储比较简单,先看这部分,其实就是实现了一个类似Tree的数据结构来存储整个脚本逻辑,然后每个单独的Case都存储在单独的Cell里(Cell为该自定义数据结构的基础单元,于单个Case对应)。Cell的结构如下(简单的实现了形如右边图片的的数据结构)http://images2015.cnblogs.com/blog/209007/201509/209007-20150916201515336-524217912.jpg                        http://images2015.cnblogs.com/blog/209007/201509/209007-20150916201557929-1676533968.jpg
其实很容易看出来这个结构跟TreeView的结构十分类似,其实最初脚本数据的存储是直接借助于TreeView的,不过为了将业务跟UI完全分离以便未来向其他平台移植时不受UI框架的影响,还是自行实现了这样的数据结构。Cell结构本身十分简单,有3个主要的结构指针childCellList    指向子CellnextCell          指向下一个CellparentCell       指向父Cell还有2个数据源caseXmlNode      指向元素的脚本数据,保留原始数据的地址是为了方便AutoTest对脚本的直接修改(这里使用的XML,如果希望相关脚本文件类型需要修改此处及脚本解析部分)caseRunData       已经解析完成的单Case数据(实际加载脚步时对所有脚本解析一次,把结果存储在这里,后面的执行即直接取这里的数据以提高性能)另外包含2个辅助元素caseType            指示该Cell即Case的实类型,可以辅助处理异常Cell的数据。uiTag                  可选的指针,用于数据绑定,名字也提示了主要用于绑定UI(实际可用绑定任何类型的数据)该机构还提供一些其他功能如Cell的容器及索引器等有兴趣的可以看下下面的Code
http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif View Code

执行的实体CaseExecutiveActuator本身会较多点,介绍的也会粗略些,不过大体也是可以简单的分成2个部分。可以很容易的想到假如我们得了脚本文件,那么有2个问题:第一就是怎么知道选择哪一个case,当前case执行完成后执行哪一个,第二个问题就是case中包含的业务如何执行。CaseExecutiveActuator也正是分成了这2部分
[*]myCaseRunTime                                  负责指引Case路径,Cell的寻找,跳转及序列的指示 都是由它完成的
[*]CaseActionActuator                           负责Case的具体执行,包括对各种协议的执行,及对结果的分析及储存,断言的处理,附加动作如语音提示,重试等执行相关的部分就由它处理

先来看比较简单的CaseRunTime   http://images2015.cnblogs.com/blog/209007/201509/209007-20150916212255133-1709810790.jpg
实际上于CaseRunTime紧密相关的还有另外2个组件myCaseLoop,myCsaeQueue(他们实际上也仅被CaseRunTime 使用)通过名字其实大概可以猜到他们的功能
[*]myCaseLoop                                 控制一组Case(可以是由多个Case组成的业务)的循环执行,当然支持循环里无限嵌套其他的循环
[*]myCsaeQueue                          控制一个逻辑项目的Case坐标(当前执行的Case),基础的Case会放在一个个逻辑项目中,每个逻辑下项目可以标识一类业务的集合,而当前执行Case是可以在这些逻辑项目中来回跳转的,所以它负责多个逻辑项目的寻址
[*]myCaseRunTime                           借助前面的CaseLoop 和CsaeQueue,完成整个Case的移动轨迹(这个轨迹可能因执行结果不同而有不同的变化,取决于脚本文件如何写)
[*]RunCaseCount                              一个辅助类,帮助统计脚本中实际将要执行的Case数量(会考虑起始点及循环等因素)

单独看看myCaseRunTimehttp://images2015.cnblogs.com/blog/209007/201509/209007-20150916215453976-1229211099.jpg如上图可以看到myCaseRunTime实际上是包含了一个myCsaeQueue列表的,不过逻辑的核心是nextCase。有兴趣的可以看看下面的实现(贴出的只包含关键部分)http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif View Code

而最终myCaseRunTime也是为CaseActionActuator 服务的,现在来看下CaseActionActuator。CaseActionActuator相对比较多一点,因为要完成的功能会多一些,跟其他模块的联系也会大一些http://images2015.cnblogs.com/blog/209007/201509/209007-20150916231931539-1034228731.png
这个可能看起来就很乱了,上图的模块主要就是一个Case文件的在系统中的表现,可以理解为一个User,这个User通过Case脚本文件可以执行一套业务,执行过程也是独立的,环境,线程,数据也都是独立的。所以可以创建任意多个这种模块以模拟大量的用户同时操作,当然脚本可以使用不同的脚本文件,也可以使用相同脚本文件(若使用相同脚本文件系统会对当前模块进行深度克隆,克隆的用户共享部分不会影响运行的数据)。该模块还可以选择以Cell对UI控件进行绑定,以达到执行过程中用户界面的友好反馈,当然不同的UI控件的动态效果需要单独的处理(处理由另一个辅助模块myActionActuator完成)这个模块的图起来乱点,不过code相对清晰,有兴趣可以看下面代码(贴出的是关键部分)http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif View Code

同时CaseActionActuator还包含一个比较重要的部分myCaseProtocolEngine,该部分是协议引擎,实际上只要PC上可以使用的协议通过简单的修改都可以加入到系统http://images2015.cnblogs.com/blog/209007/201509/209007-20150916235144851-549335018.png对于协议引擎必须继承规定好的接口实现,然后就能将协议加入系统,具体方法见【http://www.cnblogs.com/lulianqi/p/4773268.html】这个模块还要许多其他部分比如Case文件的解析,及其他可以自定义的内容这里就不继续讲下去了,有兴趣的可以下载完整代码。
辅助工具模块MyCommonToolMyCommonTool其实包含的东西也比较多不过功能都相对独立,见下图http://images2015.cnblogs.com/blog/209007/201509/209007-20150917001325289-2004429833.jpg可以看到这个模块完全是由一个个独立的类组成,相互之间的联系非常少。有很多子模块提供不同的服务通过命名也大概可以看出来VoiceService提供语音服务,myWebTool提供web服务,myEncryption提供加密服务等等,它被系统的很多模块使用。由于类比较多而又没有什么逻辑上的联系,这里同样不继续讲下去了。需要了解的可以下载完整的代码

辅助UI显示模块MyControl这个部分主要与UI的形式与呈现有关,当然包括了很多定制的数据的banding,在AutoTest及RemoteService都会用到里面的东西。不过针对不同的界面框架这部分是不能重用的。所以也不用怎么看,稍微贴张图吧。http://images2015.cnblogs.com/blog/209007/201509/209007-20150917002543461-231175346.jpg
主程序界面AutoTest对于AutoTest本身已经没有太多执行相关的逻辑处理了(都由CaseExecutiveActuator来处理),其主要处理case的呈现,及执行过程中的动态修改,还包括报告的格式化输出,同时还要2个重要功能组织多个User(执行体)跟连接远程测试主机。先稍微过下界面相关的内容,如下图http://images2015.cnblogs.com/blog/209007/201509/209007-20150917003838883-11283093.jpg                               http://images2015.cnblogs.com/blog/209007/201509/209007-20150917004756054-70470211.jpg
[*]AutoTest                                                            这当然是主体
[*]AutoTest.myDialogWindow                                  这里包含UI系统下的除主体外的其他UI窗口(右边的图展开了该项,可以看下)
[*]AutoTest.myControl                                             同样是个UI控件的定制集合,不过这里的控件仅在AutoTest适合使用
[*]AutoTest.myTool                                                工具类,为AutoTest 的行为提供便利
[*]AutoTest.RemoteServiceReference                     分布式远程访问模块,这个模块是引用WCF自动生成的,用于连接远程主机(这里WCF使用的自承载方式,程序运行时并不需要去配置什么其他的内容)

现在来看刚刚提到的一个重要的功能组织多个User,AutoTest可以创建任意多个虚拟执行体User,他们存储在CaseRunner中,同时CaseRunner还提供一些对User的基本的控制功能,如下图http://images2015.cnblogs.com/blog/209007/201509/209007-20150917005903070-131072584.jpg而这个部分其实放在逻辑层更加合适,不过之前设计经验不足。把CaseRunner于UI控件十分深的banding在一起了。绑定效果如下图http://images2015.cnblogs.com/blog/209007/201509/209007-20150917010509367-508838807.jpg这个就是大量CaseRunner绑定的效果(这个不是主界面,整体的显示效果可以看下【http://www.cnblogs.com/lulianqi/p/4773146.html】)
当然还有前面提到的另外一个重要功能连接远程测试主机,主要负责连接分布式部署在其他PC上的执行模块(就是后面要讲的RemoteService),同时可以控制及配置远程主机上的User(还包括连接的维持)。连接功能由RemoteClient组件来完成,它在前面提到的AutoTest.myTool 下,简单看下它的实现基本结构如下图http://images2015.cnblogs.com/blog/209007/201509/209007-20150917015303476-624209477.jpg这个其实实现起来比较简单,因为借助WCF框架,很多工作框架已经做好了,不过一些通道的选择配置以及是否适合双工通信可能不是最优的,后面还需要调整,可以看下下面的codehttp://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif View Code

分布式部署服务模块RemoteService这个部分与AutoTest整体结构是相似的,在执行逻辑上也是同样依靠逻辑层的3个主要模块。而内部基于WCF单独实现了服务部分,服务内容主要包括对状态及业务返回数据进行过滤重组然后上报给连接的控制机,还有接收及处理控制机的控制或配置等命令请求。下面看一下自身的结构,如下图http://images2015.cnblogs.com/blog/209007/201509/209007-20150917123803523-143242394.jpg
可以看到结构上与AutoTest确实是大体一致的,主要看下跟分布式部署相关的2个组件
[*]ExecuteService             直接提供服务说需要的部分(是WCF的必要部分)
[*]ServerHost                  对服务连接的抽象再封装,所有对服务的操作,包括获取服务数据都通过这个组件,下层应用不直接使用ExecuteService服务(从结构关系图中也可以看出来ExecuteService只被ServerHost调用)

其他部分与远程服务没有太大关系的就不介绍了
ExecuteService 按要求实现IExecuteService接口,结构跟逻辑都比较清晰(现在这部分的设计十分简单,后期对服务内容的控制也只需要改动这个地方就可以了),直接看下下面的结构图http://images2015.cnblogs.com/blog/209007/201509/209007-20150917125256914-1606835984.jpg
ServerHost 其实就是对ExecuteService再一层的封装,加入了许多与执行数据相关的逻辑,以方便应用层面的直接调用,如下图http://images2015.cnblogs.com/blog/209007/201509/209007-20150917130021304-1791015415.jpg如上图,订阅了多个回调委托来获取数据,在内部进行处理(MessageTransferChannel_RunnerCommandCallback,MessageTransferChannel_GetAllRemoteRunnerInfoCallback),同时也定义了许多委托抛出数据给应用使用,同时还需要介绍应用的命令处理后转发给ExecuteService,当然还有一个重要的功能,服务的启动跟维持也在这里完成。下面是这个类code的具体实现http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif View Code

最后放几个动画,简单演示下Auto组件的部分功能http://images2015.cnblogs.com/blog/209007/201509/209007-20150917211741117-455637882.gif
http://images2015.cnblogs.com/blog/209007/201509/209007-20150917212252039-1116802832.gif
http://images2015.cnblogs.com/blog/209007/201509/209007-20150917213434008-382176343.gif系统代码打包下载:

页: [1]
查看完整版本: 一个基于.NET平台的自动化/压力测试系统设计简述