http://www.yangyanxing.com/article/use-watcher-in-uiautomator.html

 

今天在uiautomator中实践了watcher的用法,这个也是之前在python中使用uiautomator中比较喜欢的功能,它可以提前定义一些条件,当满足一些条件时,进行一些操作,这个常用于处理测试过程中某些意料之外的或者不知道什么时候弹出来的框而阻碍测试的正常进行。
之前在写自动化用例的时候,遇到过小米手机在安装app的时候,会弹一个框来让用户点击安装,还有弹出一个升级检测的框点击“取消”按钮,或者遇到退出的时候点击确定,当然这些完全可以在用例里写逻辑来处理,而且有些还是程序本身要测试的检测点,当然这些对于大多数测试来说没有太大的意义,所以可以将其放入一个watcher里来让uiautomator来帮你进行相应的点击处理。

查看官方文档, UiWatcher是由UiDevice来registerWatcher (String name, UiWatcher watcher),name为一个名字,这个名字相当于一个key,可以在之后的查看该watcher是否被检测到了使用和remove的时候使用

初始化UiWatcher时要重写一个checkForCondition()这个抽象方法,这个方法主要就是写一些判断哪些UiSelector是否出现了,出现了怎么处理,我重新封装了一个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void initwatch(final String name,final UiSelector checkSelecto,final UiSelector opSelector){
//将name添加到watcherNames的list中,为了tearDown方法中remove掉用
watcherNames.add(name);
final UiObject check = new UiObject(checkSelecto);
final UiObject op = new UiObject(opSelector);
mDevice.registerWatcher(name, new UiWatcher() {
//这里重写checkForCondition方法
public boolean checkForCondition() {
try {
if (check.exists()) {
op.click();
Thread.sleep(1000);
return true;
}
else{
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
 
return false;
}
});
}

checkForConditon方法的返回值是boolean值,当返回true的时候,则uidevice.hasWatcherTriggered(name) 则返回true,checkForConditon这里不用写循环,uiautomator会在测试过程中一直在循环的调用。

以下是全部代码
TestUtil.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package com.yangyanxing.test;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
 
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.core.UiWatcher;
 
public class TestUtil {
public ArrayList<String> watcherNames = new ArrayList<String>();
public UiDevice mDevice = UiDevice.getInstance();
 
public static String doCmdshell(String commond){
String s = null;
try
{
Process p = Runtime.getRuntime().exec(commond);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
 
String result = "";
while ((s = stdInput.readLine()) != null)
{
result = result + s + "\n";
}
while ((s = stdError.readLine()) != null)
{
System.out.println(s);
}
return result;
}
catch (Exception e)
{
return "Exception occurred";
}
}
//init watcher
 
 
public void initwatch(final String name,final UiSelector checkSelecto,final UiSelector opSelector){
//将name添加到watcherNames的list中,为了tearDown方法中remove掉用
watcherNames.add(name);
final UiObject check = new UiObject(checkSelecto);
final UiObject op = new UiObject(opSelector);
mDevice.registerWatcher(name, new UiWatcher() {
//这里重写checkForCondition方法
public boolean checkForCondition() {
try {
if (check.exists()) {
op.click();
Thread.sleep(1000);
return true;
}
else{
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
 
return false;
}
});
}
 
 
public static Boolean waitForUiselectorAppears(UiSelector selector,int timeout)
{
UiObject uiObject = new UiObject(selector);
return uiObject.waitForExists(timeout*1000);
}
 
}

UitestRunner.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.yangyanxing.test;
 
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import static com.yangyanxing.test.TestUtil.doCmdshell;
 
 
public class UitestRunner extends UiAutomatorTestCase {
//初始化一个UiDevice
private UiDevice mDevice = UiDevice.getInstance();
private TestUtil tUtil = new TestUtil();
 
public UitestRunner(){
super();
}
//写setUp()方法
public void setUp() throws Exception{
super.setUp();
//每次测试的时候都需要启动急救箱,所以将这个方法放到setUp里
doCmdshell("am start com.qihoo.mkiller/com.qihoo.mkiller.ui.index.AppEnterActivity");
System.out.println("开始测试啦。。。");
//注册一些watcher
tUtil.initwatch("ignorSafe", new UiSelector().textContains("安全上网").className("android.widget.TextView"),
new UiSelector().text("取消"));
tUtil.initwatch("agree", new UiSelector().text("同意并使用"),
new UiSelector().text("同意并使用"));
tUtil.initwatch("Noupdate", new UiSelector().textContains("升级"),
new UiSelector().text("取消"));
mDevice.runWatchers();//将watchers运行起来
}
 
//写tearDown方法,将急救箱force-stop
public void tearDown() throws Exception{
super.tearDown();
doCmdshell("am force-stop com.qihoo.mkiller");
System.out.println("用例测试完了!");
for (String watcherName : tUtil.watcherNames) {
System.out.println(watcherName+"被remove了!");
mDevice.removeWatcher(watcherName);
}
}
 
//检测急救箱启动后是否有"开始扫描"按钮
 
public void test_startScanButton() throws UiObjectNotFoundException{
UiSelector scanButton = new UiSelector().className("android.widget.Button").text("开始扫描");
if(TestUtil.waitForUiselectorAppears(scanButton, 20)){
UiObject scanoObject = new UiObject(scanButton);
if (scanoObject.click()) {
System.out.println("开始扫描 按钮被点击了!");
}else{
System.out.println("开始扫描 按钮点击失败了");
}
}else {
System.out.println("急救箱启动失败");
}
 
UiSelector exitbutton = new UiSelector().className("android.widget.Button").text("退出");
 
assertEquals(Boolean.TRUE, TestUtil.waitForUiselectorAppears(exitbutton, 120));
}
 
public void test_print(){
System.out.println("用例2开始测试了!");
}
 
}

[uiautomator篇]uiwatcher 的使用场景的更多相关文章

  1. [uiautomator篇] UiWatcher的使用

    //package com.softwinner.pad.mark3d; package com.softwinner.performance.benchmark.mark3d; import and ...

  2. [uiautomator篇][1] 官网译文

    http://www.jianshu.com/p/7718860ec657 2016.07.25 20:59 字数 3675 Android UIAutomator浅谈 --------------- ...

  3. [uiautomator篇] 基类

      package com.softwinner.performance.benchmark; /** * UiAssistant public class * @author liuzhipeng ...

  4. spark第一篇--简介,应用场景和基本原理

    摘要: spark的优势:(1)图计算,迭代计算(2)交互式查询计算 spark特点:(1)分布式并行计算框架(2)内存计算,不仅数据加载到内存,中间结果也存储内存 为了满足挖掘分析与交互式实时查询的 ...

  5. 服务端指南 数据存储篇 | 聊聊 Redis 使用场景(转)

    作者:梁桂钊 本文,是升级版,补充部分实战案例.梳理几个场景下利用 Redis 的特性可以大大提高效率. 随着数据量的增长,MySQL 已经满足不了大型互联网类应用的需求.因此,Redis 基于内存存 ...

  6. [uiautomator篇][exist 存在,但click错误]

    uiautomator定位页面元素是,定位存在的;但是click的时候,发现点的位置不对,(不知道是android系统的问题还是uiautomator的问题,初步怀疑是系统的问题)

  7. [uiautomator篇] 使用uiautomator需要导入uiautomator库

    1 修改依赖文件:build/gradle( 是在app目录下)而不是和app同级目录的build/gradle androidTestCompile 'com.android.support.tes ...

  8. [Uiautomator篇][2] UiDeviceAPI介绍

    1 https://developer.android.com/training/testing/ui-testing/uiautomator-testing.html  http://www.cnb ...

  9. [UiAutomator篇][3] 打开音乐应用的测试脚本

    package qq.test; import android.content.Context; import android.content.Intent; import android.suppo ...

随机推荐

  1. Asp_基础之C#基础

    1.两个练习题 1)编程实现46天,是几周几天 int days = 46: int weeks = days / 7: int day =days % 7: //Console.WriteLine( ...

  2. 解决Git在更新项目时报凭证错误(Authentication failed)

    报此错误,大概率原因是用户名和密码弄错了,我用的阿里云,在网上找了半天发现Git远程仓库用的用户名和密码不是阿里云登陆用的账户密码,必须另外设置: 链接:code.aliyun.com/profile ...

  3. hihocoder1821 取卡片游戏

    思路: 博弈dp. 实现: #include <iostream> #include <algorithm> #include <cstring> using na ...

  4. 【CSS】纯css实现立体摆放图片效果

    1.  元素的 width/height/padding/margin 的百分比基准 设置 一个元素 width/height/padding/margin 的百分比的时候,大家可知道基准是什么? 举 ...

  5. 一行JS搞定快速关机

    一.在本地新建一个文件js文件 JS代码: (new ActiveXObject("Shell.Application")).ShutdownWindows(); 二.设置快捷键 ...

  6. python-mysql软件下载地址

    http://sourceforge.net/projects/mysql-python/?source=dlp

  7. CNNs 在图像分割中应用简史: 从R-CNN到Mask R-CNN

    作者:嫩芽33出处:http://www.cnblogs.com/nenya33/p/6756024.html 版权:本文版权归作者和博客园共有 转载:欢迎转载,但未经作者同意,必须保留此段声明:必须 ...

  8. HTTPs与HTTP的性能

    (参考:https://blog.csdn.net/chinafire525/article/details/78911734 https://blog.csdn.net/hherima/articl ...

  9. Vue项目经验

    Vue项目经验 setInterval路由跳转继续运行并没有及时进行销毁比如一些弹幕,走马灯文字,这类需要定时调用的,路由跳转之后,因为组件已经销毁了,但是setInterval还没有销毁,还在继续后 ...

  10. 参考别人的代码写的aes加密,记录一下(AES,ECB模式,填充PKCS5Padding,数据块128位,偏移量无,以hex16进制输出)

    package org.jimmy.autosearch2019.test; import java.security.SecureRandom; import javax.crypto.Cipher ...