注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

网易杭州 QA Team

务实 专注 分享 做有态度的QA

 
 
 
 
 

日志

 
 

Java下Windows客户端UI自动化实践  

来自陈磊   2013-07-05 16:30:45|  分类: 自动化测试 |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、前期工作
1、框架介绍:twin支持Java代码进行windows客户端自动化,在被测电脑启动一个接口java指令的程序,通过他实现java的客户端UI自动化
  3、环境准备:Java环境、.NET framework3.5以上版本、下载控件辅助工具UI Spy

二、开始测试
1、我们以变速齿轮打开应用程序这个操作为例,讲解twin是如何工作的。
打开sharpclaws.xml,设置本地或远程电脑的端口,设置被测程序的name和程序路径,如图

Java下Windows客户端UI自动化实践 - 网易杭州QA - 网易杭州 QA Team
2、双击打开sharpclaws.exe,如图

Java下Windows客户端UI自动化实践 - 网易杭州QA - 网易杭州 QA Team
3、UI Spy的使用
通过UI Spy,可以查看被测程序的窗体结构,这个工具类似selenium中xpath工具的作用。如图,红色框中表示被测程序的窗体结构。
Java下Windows客户端UI自动化实践 - 网易杭州QA - 网易杭州 QA Team

点击最上层窗格,可以看到一些属性,其中我们主要关注ClassName、Control Type、AutomationId和Name,如图 

Java下Windows客户端UI自动化实践 - 网易杭州QA - 网易杭州 QA Team
 
4、打开eclipse,编写测试代码
3.1 打开被测程序

Application app = new Application(new URL("http://127.0.0.1:4444"));  //ip地址可为远程机器ip
app.open("GearNT", null); //app名字必须再sharpclaws中定义

Java下Windows客户端UI自动化实践 - 网易杭州QA - 网易杭州 QA Team
 
3.2 获取程序最上层控件,一般为window或pane

Window window = app.getWindow();

3.3 获取目标控件,主要方法有getChildren()和getDescendants()
getChildren():获取当前控件下一层的所有控件,返回类型为List,若要获取单个控件可用getChild()方法
getDescendants():获取当前控件下所有的子控件,包括下一层、下下一层,返回类型为List,若要获取单个控件可 getDescendant()方法

//获取window下一层的控件pane,通过className获取,className可在UI Spy中找到
Pane pane = window.getChild(Criteria.type(Pane.class).and(
Criteria.className("TPanel")));
//获取TSeSkinButton值的pane,这里存在多个且无法单一区别,我们用list存放
List<Pane> buttons = pane.getDescendants(Criteria.type(Pane.class)
.and(Criteria.className("TSeSkinButton")));


  3.4 获取控件并点击。从上面代码可以看到,我们获取的是pane,定义参数名的时候却用了buttons,因为Windows下的控件很多都是不标准的,有明明是按钮他的类型却不是Button,导致我们获取到的控件是不可以点击。那么这个时候直接采用click()方法是无效的,我们需要做如下操作。

buttons.get(1).click();//这是错误的方法
buttons.get(1).click(MouseButton.Left);//这是正确的

         3.5 获取控件输入文字。以上的操作,我们相当于点击了浏览按钮,此时会跳出对话框,如图。

Java下Windows客户端UI自动化实践 - 网易杭州QA - 网易杭州 QA Team
我们需要输入要变速的文件路径再点击按钮打开。代码如下:


List<Window> windows = app.getWindows();//由于是新出现的窗口,我们需要重新获取一遍
ComboBox cb = windows.get(0).getDescendant(Criteria.type(ComboBox.class).and( Criteria.name("文件名(N):")));//获取文本框 cb.getChild(Criteria.type(Edit.class).and(Criteria.name("文件名(N):"))).type("path"); 
  Button btn = windows.get(0).getChild( Criteria.type(Button.class).and(Criteria.name("打开(O)"))); 
btn.click();


3.6 最后我们需要点击加速的倍数

Pane trackBar = pane.getDescendant(Criteria.type(Pane.class)
.and(Criteria.className("TSeSkinTrackBar")));//trakerBar居然是pane类型的,那么只能用坐标点击操作了
int x = trackBar.getLocation().x;
int y = trackBar.getLocation().y;
Desktop desktop = app.getDesktop();//由于获取的坐标是相对于整个屏幕的坐标,我们需要获取desktop 来点击
desktop.click(x + 150, y + 18, MouseButton.Left);//控件的高度和宽度可以从UI Spy中获取,这我们点击的点就确定了


这样我们就大功告成了。这就是整个UI自动化的流程。
在实际应用中,可以和testng、结合使用,若有服务端web页面的操作可以用selenium,最后把他们都部署到CI平台上,每日构建。

附录完整代码

public void openSpeeder(String path) { Application app = null; try { app = new Application(new URL("http://127.0.0.1:4444")); app.open("GearNT", null); Thread.sleep(4000); Window window = app.getWindow(); Pane pane = window.getChild(Criteria.type(Pane.class).and( Criteria.className("TPanel"))); List<Pane> buttons = pane.getDescendants(Criteria.type(Pane.class) .and(Criteria.className("TSeSkinButton"))); buttons.get(1).click(MouseButton.Left); Thread.sleep(2000); List<Window> windows = app.getWindows(); ComboBox cb = windows.get(0) .getDescendant( Criteria.type(ComboBox.class).and( Criteria.name("文件名(N):"))); cb.getChild(Criteria.type(Edit.class).and(Criteria.name("文件名(N):"))) .type(path); Button btn = windows.get(0).getChild( Criteria.type(Button.class).and(Criteria.name("打开(O)"))); btn.click(); Thread.sleep(2000); Pane trackBar = pane.getDescendant(Criteria.type(Pane.class).and( Criteria.className("TSeSkinTrackBar"))); int x = trackBar.getLocation().x; int y = trackBar.getLocation().y; Desktop desktop = app.getDesktop(); desktop.click(x + 150, y + 18, MouseButton.Left); logger.info("加速器打开xx并加速成功!"); Thread.sleep(4000); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }




 
 
  评论这张
 
阅读(1813)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016