uiautomator Tutorial

  • Brief introduction

    UiAutomator is Google's Android a Java library used for automated testing, based on Accessibility Service. It features a strong, third-party App can be tested to obtain an arbitrary APP of any property of a control on the screen, and any of its operations, but there are two drawbacks: 1 test scripts can only use the Java language 2. Test Script to be packaged into a jar or apk package upload to run on the device.

  • Environment to build

  1. Install JDK, and configure the environment variables
JDK下载地址:https://pan.baidu.com/s/1Sa6Dq2a3zciuZ_9udcDwPQ    提取码:ybe7
  1. Download the SDK, unzip
SDK下载地址:https://pan.baidu.com/s/1vMASKxDfsx6wo4MwhiVKnw    提取码:j525

  1. adb environment variable configuration
https://blog.csdn.net/shengmer/article/details/79027828
  1. Download eclipse, unzip
eclipse下载地址:https://pan.baidu.com/s/1IXIS23S52zUG80nakaAlXQ    提取码:t1ye
  1. Download jar package
jar包下载地址:https://pan.baidu.com/s/1Wv5HbN5skX4oESLDR52WHA    提取码:igge
  • New Project

  1. Open eclipse, the new java project
点击File --> New --> Java Project --> 填写项目名 --> 点击Finish

  1. In the New Project root directory of the new libs folder will start downloading the jar package, after decompression, into the libs folder and references
1:右键项目名 --> New --> Folder

2:在Folder name 栏目填写 libs --> 点击Finish

3:将开始下载的jar包,解压之后,放入libs文件夹

4:右键jar包 --> Build Path --> Add to Build Path

  1. Start coding
1:新建类,继承 UiAutomatorTestCase
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
public class xxx extends UiAutomatorTestCase {

}
2:在新建类中,写一个必须包含test字样的公开的空返回值方法
public class xxx extends UiAutomatorTestCase {
	public void testDemo() {

	}
}
3:在新建方法中,开始编写自动化代码
4:代码打包

New MyInjectEventApp.bat in the project root directory file, then right to edit, write:

del classes.dex
del bin\uiTests.jar

cd bin

jar cvf  uiTests.jar *

copy uiTests.jar ..\uiTests.jar

cd ..

set PATH=%PATH%;D:\android\adt-bundle-windows-x86_64-20140702\sdk\build-tools\android-4.4W
cmd /c dx --dex --output=.\classes.dex .\uiTests.jar

aapt add test.jar classes.dex

cd bin

Description:
D: \ Android \ ADT-bundle-Windows-x86_64-20140702 \ sdk \ Build-Tools \ android-4.4W SDK files are downloaded above inside android-4.4W directory.
test.jar packaged jar package name is complete when the
basic wording, then modify these two places on ok.
After the changes, save the file, double-click MyInjectEventApp.bat, wait for the complete package.

5:执行打包代码
新建test.bat 文件,写入:
adb push ./test.jar /data/local/tmp/

adb shell uiautomator runtest /data/local/tmp/test.jar -c com.test.xxx -e minWait 2 -e maxWait 5 -e wordType 1

Description:
adb the Push: the complete package test.jar script file, and pushed to your phone / data / local / tmp / directory
adb shell uiautomator runtest: execution / data / local / tmp / directory of the script file test.jar

-c specify package name parameter to specify the script class name received -e + (note the space no less)

Example scripts receive parameters

public class xxx extends UiAutomatorTestCase {
	private int min,max;
	private String wordType;
	public void testDemo() {
		wordType = getParamsVal("wordType", "1");    
		min = Integer.parseInt(getParamsVal("minWait","2"));
		max = Integer.parseInt(getParamsVal("maxWait","8"));
	}
	
	private Bundle params = null;
	//第一个参数:-e 后面的字段 
	//第二个参数:在获取不到第一个参数的时候,设置的默认值
	public String getParamsVal(String key, String defVal) {
		String val = "";
		if (null == params)
			params = getParams();
		if (params.isEmpty()) {
			return defVal;
		}

		if (params.containsKey(key)) {
			val = params.getString(key);
			if (null == val) {
				val = defVal;
			}
		} else {
			val = defVal;
		}
		return val;
	}
}



  • uiautomatorviewer use

After the phone is connected to the computer, locate the sdk \ tools \ bin \ uiautomatorviewer.bat file, double-click.

Click this button to get a cell phone screen

If I want to get " dynamic message information" to get out in uiautomatorviewer page, point " news feed ", can be seen on the right.

这里可以拿到 “动态消息” 的 text, resource-id,class, content-desc 等信息。

If I want to get the coordinates of a location.

这里可以拿到当前鼠标位置的坐标(309,548)
  • Detailed uiautomator API

UiDevice common method

In automated testing can UiDevice objects to control by the apparatus, such as light up the screen, the lock screen, the rotational direction, captures, etc., home button click, Back key, menu key and the like.

pressBack () // simulate a click on the phone back key

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	uiDevice.pressBack(); //模拟点击返回键
}

wakeUp () // wake up the screen

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	uiDevice.wakeUp(); //唤醒屏幕,如果屏幕是处于唤醒状态,则无效
}

pressHome () // click the home button

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	uiDevice.pressHome(); //点击home键
}

click (int x, int y) // coordinates (x, y) coordinates of the point and click interface

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	uiDevice.click(50, 80); //点击界面上坐标为(50,80)的坐标点
}

getDisplayHeight () // get the screen height

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	int height = uiDevice.getDisplayHeight(); //获取屏幕高度
}

getDisplayWidth () // get the screen width

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	int width = uiDevice.getDisplayWidth(); //获取屏幕宽度
}

pressEnter () // analog Press ENTER

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	uiDevice.pressEnter(); //模拟短按回车键
}

pressMenu () // analog Press menu key

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	uiDevice.pressMenu(); //模拟短按menu键
}

pressKeyCode (int keyCode) // analog Press key codes keycode

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	uiDevice.pressKeyCode(KeyEvent.KEYCODE_NUMPAD_ENTER); //模拟按回车键
}

swipe (startX, startY, endX, endY, steps) // slide

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	uiDevice.swipe(10, 10, 100, 100, 50);   //从坐标点(10,10) 滑动到 坐标点(100,100) ,步长为50
}

takeScreenshot (file) // Screenshot

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	String path = /data/local/tmp/" + "Tmp_" + System.currentTimeMillis() + ".png;
    File file = new File(path);   //根据文件名创建文件
	uiDevice.takeScreenshot(file);    //截图
}

registerWatcher (name, watcher) // Listener

public void testDemo() {
	UiDevice uiDevice = UiDevice.getInstance();  // 获取UiDevice
	uiDevice.registerWatcher("tips", new UiWatcher() {  
	        //tips:监听器名字
			@Override
			public boolean checkForCondition() {
				// TODO Auto-generated method stub
				
				boolean isTrue = false;
				if (isTrue) {
					System.out.println("tipUiWatcher start!!!!");
					return true;
				}
				return false;
			}
		});
	//监听器,不建议写在循环里面。
	//这段代码的意思:创建一个名为tips的监听器,在脚本执行期间,如果当isTrue = true 时,触发监听器。
}

UiDevice temporarily introduce several of the most commonly used method


Find a common method of control

Find controls by resource-id, if so, Click

public class xxx extends UiAutomatorTestCase {
	public void testDemo() throws UiObjectNotFoundException {
		UiObject uiObject = new UiObject(new UiSelector().resourceId("通过 uiautomatorviewer 查看到的id"));
		//设置5S ,等待控件出现,如果控件出现的时间小于5s,则正常执行
		//5s只是一个等待控件出现的最大时间,这里可以自行设置
		uiObject.waitForExists(5000);    
		if(uiObject.exists()) {   // 如果当前界面能找到这个 元素
			uiObject.click();     // 点击
		}
	}
}

Find controls by class, if there is, then click

public class xxx extends UiAutomatorTestCase {
	public void testDemo() throws UiObjectNotFoundException {
		UiObject uiObject = new UiObject(new UiSelector().className("通过 uiautomatorviewer 查看到的 class"));
		//设置5S ,等待控件出现,如果控件出现的时间小于5s,则正常执行
		//5s只是一个等待控件出现的最大时间,这里可以自行设置
		uiObject.waitForExists(5000); 
		if(uiObject.exists()) {   // 如果当前界面能找到这个 元素
			uiObject.click();     // 点击
		}
	}
}

Find controls by content-desc, if so, Click

public class xxx extends UiAutomatorTestCase {
	public void testDemo() throws UiObjectNotFoundException {
		UiObject uiObject = new UiObject(
				new UiSelector().description("通过 uiautomatorviewer 查看到的 class"));
		//设置5S ,等待控件出现,如果控件出现的时间小于5s,则正常执行
		//5s只是一个等待控件出现的最大时间,这里可以自行设置
		uiObject.waitForExists(5000); 
		if(uiObject.exists()) {   // 如果当前界面能找到这个 元素
			uiObject.click();     // 点击
		}
	}
}

Find controls through the text, if there is, then click

public class xxx extends UiAutomatorTestCase {
	public void testDemo() throws UiObjectNotFoundException {
		UiObject uiObject = new UiObject(new UiSelector().text("通过 uiautomatorviewer 查看到的text"));
		//设置5S ,等待控件出现,如果控件出现的时间小于5s,则正常执行
		//5s只是一个等待控件出现的最大时间,这里可以自行设置
		uiObject.waitForExists(5000);
		if(uiObject.exists()) {   // 如果当前界面能找到这个 元素
			uiObject.click();     // 点击
		}
	}
}

In addition to the control by a single property to find outside, but also by the way to find a combination of controls, such as:

//通过id和text 组合查找控件
UiObject uiObject = new UiObject(new UiSelector().resourceId(id).text(text));

//通过id和description 组合查找控件
UiObject uiObject = new UiObject(new UiSelector().resourceId(id).description(description));

The other, you can mix your own.

To the input box contents

首先找到文本输入框
public class xxx extends UiAutomatorTestCase {
	public void testDemo() throws UiObjectNotFoundException {
		//先根据id,找到文本输入框,然后调用setMsgToEdit方法
		UiObject uiEdit = new UiObject(new UiSelector().resourceId("jp.naver.line.android:id/chathistory_message_edit"));
		if(uiEdit.exists()) {
			setMsgToEdit("你好");
		}
	}
	
	public void setMsgToEdit(String string) {
		try {
			string = URLDecoder.decode(string, "UTF-8");
		} catch (Exception e) {
		}
		try {
			Thread.sleep(500);
		} catch (Exception e) {
		}

		IClipboard iClipboard = IClipboard.Stub
				.asInterface((IBinder) ServiceManager.getService("clipboard"));
		// IInputManager.Stub.asInterface((IBinder)ServiceManager.getService("input"));
		try {
			iClipboard.setPrimaryClip(
					ClipData.newPlainText("NonASCII", string), string);
		} catch (RemoteException var1_2) {
			var1_2.printStackTrace();
		}
		paste();
		try {
			iClipboard
					.setPrimaryClip(ClipData.newPlainText("NonASCII", ""), "");
		} catch (Exception e) {
		}
	}

	private void paste() {
		UiDevice.getInstance().pressKeyCode(50, 4096);
	}
}

Find a list, circular list, click on each friend, and returns:

首先找到列表,分析列表的元素,

当前界面列表元素为:class:androidx.recyclerview.widget.RecyclerView  resource-id:jp.naver.line.android:id/friend_list_recycler_view
所以:这里有两种方法去找到当前列表
第一种为通过 resource-id 查找列表
第二种为通过 class 查找列表
public class xxx extends UiAutomatorTestCase {
	public void testDemo() throws UiObjectNotFoundException {
	//注意,查找列表的时候,跟查找其他控件不一样,列表必须要使用UiScrollable
		UiScrollable uiScrollable = new UiScrollable(
				new UiSelector().resourceId("jp.naver.line.android:id/friend_list_recycler_view"));
		//设置5S ,等待控件出现,如果控件出现的时间小于5s,则正常执行
		//5s只是一个等待控件出现的最大时间,这里可以自行设置
		uiScrollable.waitForExists(5000); 
		if(uiScrollable.exists()) {   // 如果当前界面能找到这个 元素
			//其他逻辑
		}
	}
}
public class xxx extends UiAutomatorTestCase {
	public void testDemo() throws UiObjectNotFoundException {
		//注意,查找列表的时候,跟查找其他控件不一样,列表必须要使用UiScrollable
		UiScrollable uiScrollable = new UiScrollable(
				new UiSelector().className("androidx.recyclerview.widget.RecyclerView "));
		//设置5S ,等待控件出现,如果控件出现的时间小于5s,则正常执行
		//5s只是一个等待控件出现的最大时间,这里可以自行设置
		uiScrollable.waitForExists(5000); 
		if(uiScrollable.exists()) {   // 如果当前界面能找到这个 元素
			//其他逻辑
		}
	}
}
展开列表元素

通过工具可以看到,消息列表的class :android.widget.LinearLayout,resource-id:jp.naver.line.android:id/bg 所以:
public class xxx extends UiAutomatorTestCase {
	public void testDemo() throws UiObjectNotFoundException {
		//注意,查找列表的时候,跟查找其他控件不一样,列表必须要使用UiScrollable
		UiScrollable uiScrollable = new UiScrollable(
				new UiSelector().className("androidx.recyclerview.widget.RecyclerView"));
		//设置5S ,等待控件出现,如果控件出现的时间小于5s,则正常执行
		//5s只是一个等待控件出现的最大时间,这里可以自行设置
		uiScrollable.waitForExists(5000); 
		if(uiScrollable.exists()) {   // 如果当前界面能找到这个列表
			//uiScrollable.getChildCount()  当前列表,在当前界面,能看到的条数
			for (int i = 0; i < uiScrollable.getChildCount(); i++) {
				// 循环遍历当前列表,第一级元素控件
				UiObject uiItem = uiScrollable.getChild(new UiSelector().className(
						"android.widget.LinearLayout").index(i));
				if(!uiItem.exists()) continue;  // 如果控件不存在,跳过当前循环,进入下一次循环
				
			}
		}
	}
}
上面找到了第一级目录,而通过工具可以看到,需要点击好友,需要分析第一级目录下面子元素的个数
public class xxx extends UiAutomatorTestCase {
	public void testDemo() throws UiObjectNotFoundException {
		//注意,查找列表的时候,跟查找其他控件不一样,列表必须要使用UiScrollable
		UiScrollable uiScrollable = new UiScrollable(
				new UiSelector().className("androidx.recyclerview.widget.RecyclerView"));
		//设置5S ,等待控件出现,如果控件出现的时间小于5s,则正常执行
		//5s只是一个等待控件出现的最大时间,这里可以自行设置
		uiScrollable.waitForExists(5000);
		if(uiScrollable.exists()) {   // 如果当前界面能找到这个 元素
			//uiScrollable.getChildCount()  当前列表,在当前界面,能看到的条数
			for (int i = 0; i < uiScrollable.getChildCount(); i++) {
				// 循环遍历当前列表,第一级元素控件
				UiObject uiItem = uiScrollable.getChild(new UiSelector().className(
						"android.widget.LinearLayout").index(i));
				if(!uiItem.exists()) continue;  // 如果控件不存在,跳过当前循环,进入下一次循环
				
				//获取uiItem下面子元素的个数
				int size = uiItem.getChildCount();
				
				//当子元素个数大于2的时候,说明不是好友,而是其他项,所有,过滤,不点击。
				if(size > 2) continue;
				
				//点击单个好友
				uiItem.click();
				
				//让程序休息一会,等待相应
				sleep(3000);
				
				//因为点击了好友,会跳转转到另外一个界面, 所以,需要一个点击返回的操作。
				UiDevice.getInstance().pressBack();
			}
		}
	}
}
Published an original article · won praise 0 · Views 1525

Guess you like

Origin blog.csdn.net/JianXiongx/article/details/100882993