背景

  Windows客户端产品基于UI的自动化测试自古以来都比较难做,基于非标准控件的UI自动化更是难上加难。进程间基于UI的自动化测试会对产品UI布局有很大依赖,产品布局的每一次改动都可能会使相关自动化测试用例失效。

  于是我们需要一种可以动态跟随UI变化的机制,可以在运行时确定UI的布局,进而实施相应UI自动化测试。除了获取UI布局外,像UI的一些状态信息(位置、文字等),对自动化测试也是非常必要。为此,我们采用代理的方式,以“假注入”的形式实现了对主程序运行时状态的获取。

  概述

  被测产品的Proxy是由运行于产品进程当内的命令处理模块(ProxyAgent)和运行于进程外的适配器模块(ProxyAdapter)组成的。 ProxyAgent模块运行于产品进程内可以带来很多便利,一是上面提到的可以动态获取产品的状态信息,二是增加了测试人员的主动权,因为测试代码与产品代码同源,许多操作不需要再请求开发人员来实现,测试人员自己可以安排人员去实现。ProxyAdapter从名字可以看出为适配器层,它屏蔽了C++ 的复杂接口,为上层调用者提供了标准的Python接口。

  Proxy结构

  被测产品在代码层面进行了支持,通过加载动态链接库的方式实现。整个Proxy由两部分组成:产品内代理层和产品外协议适配器层。

  ※ 产品内代理层(ProxyAgent)。产品进程内DLL,它接收命令、查询并返回产品UI的状态信息。

  ※产品外协议适配器层(ProxyAdapter)。转发用户命令、接收进程内ProxyAgent返回信息并提供Python接口,方便上层自动化库调用。

图1 Proxy在自动化库中的结构

  实现机制

  Proxy为产品进程内动态链接器,与产品工程同源,可以方便地引用产品当中的各种库和头文件,相当于产品的测试后门,理论上讲ProxyAgent可以协助测试发起任何产品支持的动作。ProxyAdapter为独立的适配器层,可独立编译,它向上为python提供接口,中间将命令信息进行转化,下层与进程外的Proxy打交道,进行信息交换。ProxyAgent与ProxyAdaper的出现使测试代码可以直接获取运行中产品的信息,大大提高了系统级测试的效率。增加Proxy前后示意图如图2所示

图2 无代理VS有代理

  ProxyAgent实现机制

  ProxyAgent实质上是一个进程内DLL,此DLL提供初始化接口和反初始化接口,开发人员判断指定的DLL是否存在,若存在则调用此DLL的初始化接口,产品退出时调用反初始化接口。产品当中,初始化时ProxyAgent建立隐藏窗体,用来接收运行中发过来的消息;反初始时销毁隐藏窗体。流程如图3

图3 ProxyAgent生命周期

  ProxyAdapter实现机制

  本模块通过Windows消息和共享内存来传递命令,与产品当中的ProxyAgent实现交互。产品状态信息通过共享内存实现。在本层进行了封装,将调用接口封装成python接口,方便上层python关键字库调用,可以降低用例编写成本。