uiautomator 2.0使用
1.关于UIAutomator2.0与1.0的区别
网上很多教程都是关于1.0版本的,而2.0版本从表象上,可以看做是在API上进行的丰富(例如APP的启动方式),以及缺陷的修补(例如不支持中文)。若未接触过1.0,可以直接忽略。
两者的主要区别如下
(a)2.0基于 Instrumentation, 可以获取应用Context,可以使用Android服务及接口。
(b)2.0基于 Junit4,测试用例无需继承于任何父类,方法名不限,使用Annotation进行, 1.0需要继承UiAutomatorTestCase,测试方法需要以test开头。(c)2.0采用Gradle进行构建,1.0使用Maven或Ant。
(d)2.0新增UiObject2、Until、By、BySelector等接口。
(e)2.0输出到Logcat,1.0可以使用System.out.print输出流回显至执行端。
(f)2.0输出为APK,1.0输出为JAR。
2.基于Android Studio的UIAutomator2.0工程
(a)创建一个简单的Android工程(有无Activity无所谓)。
(b)在对应module的build.gradle文件中,添加对uiautomator的dependends引用
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.0.0-beta1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:0.5'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
// androidTestImplementation 'androidx.text.uiautomator:uiautomator:2.2.0'
androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
}
Android通过Annotation来识别测试用例
(a)通过声明@RunWith(AndroidJUnit4.class),来表示该类为一个测试集合。
(b)通过声明@Test,来表示该方法为一个测试用例。
3.一个简单的测试用例
package test.com.uiautomatortest.testcase;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.util.Log;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import java.io.File;
import java.io.IOException;
import test.com.uiautomatortest.CommonMethod;
/**
* 文件管理测试
*
*/
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class FileManagerTest {
private static final String TAG = "FileManagerTest";
private String mPackageName = "X.x.x.X";
private String mLaunchActivityName = ".X.X.X";
public final String UpanString = "1xxxxxxXXXX";
public final String testResourceFileText = "00A";
public final String testAudoText = "audio";
public final String pictureText = "picture";
public final String videoText = "video";
public final String listBtn = "x.x.x.x:id/layout_list_grid";
public final String audio_1_text = "FenShouShuoAiNi.mp3";
public int timeout = 5000;
public static UiDevice mDevice;
CommonMethod cm = new CommonMethod();
private static String path;
@BeforeClass
/**
* 该方法将在测试案例集(class)实例创建前执行。因此,该方法必须为static类型,仅被执行一次。相当于初始化测试平台环境。
*/
public static void init() {
Log.i(TAG, "init");
Context context = InstrumentationRegistry.getTargetContext();
path = context.getExternalCacheDir().getPath();
Log.i(TAG, "init: path = " + path);
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// mDevice.pressHome();
}
@Before
/**
* 用于声明方法,该方法将在每个测试案例(function)被调用前执行,因此,该方法可根据测试案例数量,被多次执行,相当于初始化测试上下文。
*/
public void OpenApp() throws InterruptedException {
Log.i(TAG, "OpenApp");
cm.startApp(mPackageName);
mDevice.waitForWindowUpdate(mPackageName, 2000);
Thread.sleep(3000);
}
@Test
public void test1() throws InterruptedException {
//点击到U盘目录
UiObject2 UpanItem = mDevice.findObject(By.text("1xxxxxxXXXX"));
UpanItem.click();
mDevice.waitForWindowUpdate(mPackageName, timeout);
//切换到列表展示
UiObject2 ChangelistBtn = mDevice.findObject(By.res(listBtn));
ChangelistBtn.click();
mDevice.waitForWindowUpdate(mPackageName, timeout);
//点击测试资源目录00A
UiObject2 testResourceBtn = mDevice.findObject(By.text(testResourceFileText));
testResourceBtn.click();
mDevice.waitForWindowUpdate(mPackageName, timeout);
//点击进入音频目录
// UiObject2 testAudioBtn = mDevice.findObject(By.res("x.x.x.x:id/layout_img"));
try {
UiObject2 testAudioBtn = cm.findObjectAndWait(mDevice, By.text(testAudoText), 20000, TAG);
testAudioBtn.click();
} catch (Exception e) {
e.printStackTrace();
}
mDevice.waitForWindowUpdate(mPackageName, timeout);
//点击第一首音乐播放
// UiObject2 audio_1 = mDevice.findObject(By.text(audio_1_text));
try {
UiObject2 audio_1 = cm.findObjectAndWait(mDevice, By.text(audio_1_text), 20000, TAG);
audio_1.click();
mDevice.waitForWindowUpdate(mPackageName, timeout);
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
@After
public void closeAPP() {
Log.i(TAG, "closeAPP");
cm.closeApp(mDevice, mPackageName, TAG);
}
/**
* 该方法将在测试案例集合(class)实例销毁前执行。因此该方法也必须为static 类型,仅被执行一次,相当于清理测试平台环境。
*/
@AfterClass
public static void destroy() {
Log.i(TAG, "destory");
mDevice = null;
}
}
原文链接:https://blog.csdn.net/daihuimaozideren/article/details/78331673
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现