https://segmentfault.com/a/1190000010339021

从事Windows 桌面应用自动化测试也有一些年了,现在谈这个话题并不流行。因为除了企业级应用,很少有公司会只选择Windows桌面作为目标用户平台,一般都会考虑跨平台的浏览器解决方案,桌面应用的地位渐渐下降,这是事实。

当年初入测试行业时就被外包公司看上了,在微软的圈子里一待就是4年,时间真快。不得不说,一个大学刚毕业的毛头小子看到微软里各种技术和工具真像极了刘姥姥进大观园,那时候还没有iPhone,也没有Android,微软一统天下。

本文主要介绍一下我对Windows UI自动化的一些看法以及WPATH的实现和应用,如果你还在从事Windows桌面应用的自动化测试,应该能有一些帮助。

为何发明WPATH

Windows UI 自动化,顾名思义就是在Windows平台实现软件的界面自动化,比如自动打开Excel填入一些数据,输入公式,获取结果。正经的用途就是软件自动化测试,避免重复的手工操作;不正经的用途就是写外挂,各种投机取巧的工具等等。

最简单粗暴的实现方案就是录制回放,优点很明显,简单快速;缺点也一样明显,不可靠因素太多。主要的代表就是QTP,来自HP公司,这应该是很多同学都听过的一款测试工具。

进阶的方案就是使用微软提供的自动化工具集:UI Automation。UI Automation是Microsoft .NET 3.0框架下提供的一种用于自动化测试的技术,是在MSAA基础上建立的,MSAA就是Microsoft Active Accessibility。

如果你使用过.NET 提供的UI Automation相关的类库,应该有一个直观的感受,就是非常啰嗦,举一个例子:

AutomationElement ControlTypeComboBox = grdClassBook.FindFirst(
TreeScope.Children,
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ComboBox)); AutomationElement cellElement = ControlTypeComboBox.FindFirst(
TreeScope.Children,
new PropertyCondition(AutomationElement.AutomationIdProperty, "ListBox"));

每当你尝试去获取一个UI元素时,都需要使用FindFirst之类的方法去查询指定的PropertyCondition,而PropertyCondition使用起来也不简单,特别是当你需要拼接多个AND或者OR多个条件时。

var btnCondition = new AndCondition(
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button),
new PropertyCondition(AutomationElement.NameProperty, "ok"));

才两个条件就这么多代码了?你看看搞Web自动化的同学都可以用XPATH,快速定位和查询元素 /div[@id='ok'],多好。既然我们那么羡慕XPATH,那我们就搞一个出来,让做Windows桌面自动化的同学也可以High一把。

WPATH实现原理

具体代码我就不在此赘述了,想读代码的同学可以直接移步至Github:https://github.com/tobyqin/wpath

WPATH的主要原理就是通过反射的方式去获取当前方法或者属性的Attribute,在Attribute中我们可以定义类似于XPATH的语法,我 且称之为WPATH。最后经过表达式解析转换成对应的Find方法和Condition,举一个例子说明:

[WPath("/Edit[@id='txtId' or @Class='TextBox']")]
public AutomationElement EditControl
{
get { return this.AppElement.FindByWPath(); }
}

当调用FindByWPath()时,该属性上的WPath Attribute就会被解析出来,其中的 /会被解析成FindFirst,Edit会被解析成ControlType.Edit,中括号里的条件最后被组合起来,调用的最终结果大致如下:

public AutomationElement EditControl
{
get
{
return this.AppElement.FindFirst(TreeScope.Children,
new AndCondition(
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit),
new OrCondition(
new PropertyCondition(AutomationElement.AutomationId, "txtId"),
new PropertyCondition(AutomationElement.Class, "TextBox"))));
}
}

痛苦的感觉一下减轻许多,有没有?

更详细的WPATH用法

如果你要在项目中使用WPATH,可以通过nuget包安装:

PM> Install-Package WPath

简单说明

  1. WPath 和 XPath 类似,以 '/' 开头。

  2. 可以使用多个 '/' 来定位目标元素。

  3. 节点名字来自于MSDN定义好的 control type

  4. 目前WPath支持的查询属性如下:

  • Name (NameProperty)

  • ID (AutomationIdProperty)

  • Class (ClassNameProperty)

  • Enabled (IsEnabledProperty)

  • FrameworkID (FrameworkIdProperty)

举例子

/Group/Button

  • 获取第一个Group下的第一个Button。

//Button[@Name='Save']

  • 在子孙节点中获取第一个Name为 "Save" 的元素。

/[@Name='TabContainer']/Button[2]

  • 获取Name为 "TabContainer"的控件下的第二个Button,注意,控件类型名称可以为空。

/Button[@ID='AddButton' and @Name='Add']

  • 获取一个automation ID 为 'AddButton'  name 为 'Add' 的Button。

/Button[@ID='AddButton' or @Name='Add']

  • 获取一个automation ID 为 'AddButton'  name 为'Add'的Button。

/Button[first()]

  • 获取当前元素下第一个Button。

/Button[last()]

  • 获取当前元素下最后一个Button。

实际运用

推荐使用Attribute的方式进行调用,可用于类方法或者属性。

[WPath("/Edit[@id='txtId' or @Class='TextBox']")]
public AutomationElement EditControl
{
get { return this.AppElement.FindByWPath(); }
} [WPath("/Button[first()]")]
public AutomationElement GetFirstButton()
{
return this.AppElement.FindByWPath();
}

或者直接调用 FindByWPath(path) 来定位目标元素。

var path = "/Edit[3]";
var e = this.AppElement.FindByWPath(path);
Assert.AreEqual("txtKey", e.Current.AutomationId);
Assert.AreEqual(ControlType.Edit, e.Current.ControlType); path = "/Button[@name='OK']/Text[1]";
e = this.AppElement.FindByWPath(path);
Assert.AreEqual("OK", e.Current.Name);
Assert.AreEqual(ControlType.Text, e.Current.ControlType);

小贴士

  • 元素类型节点是大小写不敏感的,比如:

    • @name = @Name

    • /edit = /Edit

  • 父节点定位 ../ 目前不支持,因为有点复杂。

更多的说明建议还是去看Github中的说明文档,或者直接看单元测试

后记

Windows UI 自动化的坑还是挺深的,填坑的人也不少,我推荐有需要的同学去学习和了解一下 White。White是一个非常好UI Automation 封装框架,相信我,能省下你不少时间。

Windows UI自动化测试的XPATH实现 - WPATH的更多相关文章

  1. 从UI Automation看Windows平台自动化测试原理

    前言 楼主在2013年初研究Android自动化测试的时候,就分享了几篇文章 Android ViewTree and DecorView Android自动化追本溯源系列(1): 获取页面元素 An ...

  2. 对Windows桌面应用程序进行UI自动化测试

    题记:本文简述如何利用appium对Windows桌面应用程序进行UI自动化测试. 所谓UI自动化测试,就是模拟一个用户,对应用程序的UI进行操作,以完成特定场景的功能性集成测试. 要对Windows ...

  3. 基于Appium的UI自动化测试

    为什么需要UI自动化测试 移动端APP是一个复杂的系统,不同功能之间耦合性很强,很难仅通过单元测试保障整体功能.UI测试是移动应用开发中重要的一环,但是执行速度较慢,有很多重复工作量,为了减少这些工作 ...

  4. 使用WatiN进行UI自动化测试

    Watin是一个UI自动化测试工具,支持ie/firefox,官方网站:http://watin.org/. 主要有以下特点: 支持主要的html元素,见:http://watin.org/docum ...

  5. 【转】Web UI自动化测试原理

    目前市面上有很多Web UI自动化测试框架,比如WatiN, Selinimu,WebDriver,还有VS2010中的Coded UI等等.  这些框架都可以操作Web中的控件,模拟用户输入,点击等 ...

  6. UI自动化测试(三)对页面中定位到的元素对象做相应操作

    前两天分别讲述了UI自动化测试基础以及对页面元素该如何进行定位,这一篇自然就是对定位到的页面元素对象进行相应操作啦. 阅读目录 1.常用操作元素对象的方法 2.鼠标事件操作 3.键盘事件操作 4.We ...

  7. <自动化测试方案_7>第七章、PC端UI自动化测试

    第七章.PC端UI自动化测试 UI自动化测试又分为:Web自动化测试,App自动化测试.微信小程序.微信公众号UI层的自动化测试工具非常多,比较主流的是UFT(QTP),Robot Framework ...

  8. [原创]浅谈Web UI自动化测试

    [原创]浅谈Web UI自动化测试 Web UI自动化测试相信大家都不陌生,今天来谈谈这个,我最早接触自动化测试时大约是在2004年,2006年当时在腾讯财付通算是开始正式接触自动化测试,之所以是正式 ...

  9. 浅谈UI自动化测试

    最近一直在学习python,正好部门技术结构调整,就开始了点工向UI自动化测试的转变,我要说瞌睡来了就掉枕头么? 不过还好,可以将python的学习成果在自动化测试中实践... 1.about自动化测 ...

随机推荐

  1. jquery如何遍历table,并对table里的某一个单元格进行操作

    1.如何根据每一行的某一列的值进行比较或其他操作,进而修改另一列的值或属性. $("#table_id tbody tr").each(function(){ var a = $( ...

  2. npm install 报错 error Unexpected end of JSON input while parsing near '...sShrinkwrap":false,"d' 解决办法

    npm install 报错 : error Unexpected end of JSON input while parsing near '...sShrinkwrap":false,& ...

  3. Lodash之throttle(节流)与debounce(防抖)总结

    全手打原创,转载请标明出处:https://www.cnblogs.com/dreamsqin/p/11305028.html 先重点说一下可能遇到的坑:主要在原本默认参数的设置以及两个方法的选择上, ...

  4. 推荐一个GOLANG入门很好的网址

    推荐一个GOLANG入门很好的网址,栗子很全 https://books.studygolang.com/gobyexample/

  5. Linux学习笔记之LVM基本应用,扩展及缩减实现

    0x00 LVM概述 LVM是逻辑盘卷管理(Logical Volume Manager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和分区之上的一个逻辑层,来提高磁盘 ...

  6. Redis 获取和设置密码

    1.config get reuqirepass //获取当前密码 2.config set requirepass "password"//设置当前密码,双引号里面为密码

  7. Redis常用配置和命令总结

    Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言 ...

  8. NVIDIA-docker Cheatsheet

    TensorFlow Docker requirements Install Docker on your local host machine. For GPU support on Linux,  ...

  9. Django:RestFramework之-------频率控制

    5.频率控制 5.1频率监控代码实现 import time VISIT_RECORD = {} class VisitThrottle(object): def __init__(self): #定 ...

  10. vue学习整理

    1.webpack+vue自定义路径别名 vue-cli 用的是webpack,也可以使用webpack自定义别名这个功能,自定义别名这个功能当你在多层文件夹嵌套的时候不必一层一层找路径,直接使用自定 ...