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 swipper插件的一些弊端

    jquery swipper插件的一些弊端touch触摸机制是swipper的 阻止click冒泡.拖动Swiper时阻止click事件.下面这个方法或许可以解决触摸机制的问题 <pre> ...

  2. Visual Studio 重命名项目名

    1. 打开VS Studio,重命名项目 2. 重命名对应的项目文件夹,并重命名项目文件夹下的这两个文件名: 3. 用记事本打开解决方案,修改对应的项目名字和路径 未完 ...... 点击访问原文(进 ...

  3. php 求商数和余数 的函数

    //返回两数相除之商和余数function get_div_and_mod($left_operand, $right_operand){ $div = intval($left_operand / ...

  4. 常用Java API之Scanner:功能与使用方法

    Scanner 常用Java API之Scanner:功能与使用方法 Scanner类的功能:可以实现键盘输入数据到程序当中. 引用类型的一般使用步骤:(Scanner是引用类型的) 1.导包 imp ...

  5. 50道Java线程面试题分析及答案

    下面是Java线程相关的热门面试题,你可以用它来好好准备面试. 1) 什么是线程?线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程 ...

  6. System.ArgumentException:路由集合中已存在名为“XXX”的路由。路由名称必须唯一。

    软件环境:Visual Studio 2017 + MVC4 + EF6 问题描述:System.ArgumentException:路由集合中已存在名为“XXX”的路由.路由名称必须唯一. 解决办法 ...

  7. ssh in depth

    前两天写了一篇关于ssh的相对比较入门的文章,重点介绍了ssh在免密登录场景下的应用. 本文试图对ssh更高级的话题做一下探讨,重点探讨一下ssh tunneling https://www.ssh. ...

  8. Spring怎么管理事务?

    我们一般通过aop管理事务,就是把代码看成一个纵向有序的,然后通过aop管理事务,就好比增删改的时候需要开启一个事务,我们给他配置一个required,required就是有事务就执行事务,没有就给他 ...

  9. Trie树的java实现

    leetcode 地址: https://leetcode.com/problems/implement-trie-prefix-tree/description/ 难度:中等 描述:略 解题思路: ...

  10. JCEF-鼠标右键菜单

    为鼠标添加自定义菜单,比较简单,实现一个Handler就行 Hanler实现类 public class MenuHandler extends CefContextMenuHandlerAdapte ...