Android调用系统内置的UiAutomator工具实现自动化测试
·
一、功能概述
- 属于Android UI 自动化测试的核心技术之一,允许应用程序在不需要人工干预的情况下,自动操作界面元素进行测试。
- 实现思路:执行指定命令,系统会将当前界面的 UI 控件信息(包括控件类型、文本内容、坐标位置等)以 XML 格式保存到指定文件中。之后,程序会解析这个 XML 文件,找到特定的控件(如按钮、文本框、输入框等),获取它们的坐标位置,进而实现自动点击、输入等操作。
- 涉及命令:/system/bin/uiautomator dump --compressed [文件路径] 。作用是使用 Android 系统内置的 uiautomator 工具来获取当前屏幕界面的布局信息,并以压缩格式保存为 XML 文件。
二、实现流程
1、核心工具类
1.1、UiAutomatorUtil
import android.text.TextUtils;
import android.util.Log;
import 你的包名.util.ShellUtil;
import java.io.File;
/**
* Description:调用系统内置的UiAutomator工具操作类
*/
public class UiAutomatorUtil {
/** 根据文本内容点击控件 */
public static boolean clickByText(String classTag, String text, String uiXmlPath) throws Exception {
// 1、调用系统内置的uiautomator工具,以压缩格式输出XML(减少文件体积),保存结果到指定路径的文件
String execCmdResult = executeUiAutomatorDump(uiXmlPath);
if (TextUtils.isEmpty(execCmdResult)) {
Log.e(classTag + "_UiAutomatorUtil", "clickByText(),执行系统内置的uiautomator工具时发生异常");
return false;
}
Thread.sleep(1000); // 确保文件写入完成
// 2、解析Xml文本内容以获取坐标
UiXmlParser.Rect bounds = UiXmlParser.findBoundsByText(new File(uiXmlPath), text);
if (bounds == null) {
Log.e(classTag + "_UiAutomatorUtil", "clickByText(),未找到文本控件: " + text);
return false;
} else {
Log.i(classTag + "_UiAutomatorUtil", "clickByText(),找到文本控件,文本内容是: " + text);
}
// 3、计算中心点并点击
UiXmlParser.Point center = bounds.getCenter();
ShellUtil.getExecCmdResult("input tap " + center.x + " " + center.y);
Log.i(classTag + "_UiAutomatorUtil", "clickByText(),点击的文本内容:" + text + ",坐标: (" + center.x + "," + center.y + ")");
return true;
}
/**
* 执行 uiautomator dump 命令,增加重试机制以提高成功率
* @param uiXmlPath XML文件保存路径
* @return 执行结果
*/
private static String executeUiAutomatorDump(String uiXmlPath) throws Exception {
String command = "/system/bin/uiautomator dump --compressed " + uiXmlPath;
String result = null;
int maxRetries = 3;
for (int i = 0; i < maxRetries; i++) {
try {
result = ShellUtil.getExecCmdResult(command);
// 检查是否包含错误信息
if (result != null && !result.contains("ERROR: could not get idle state")) {
return result;
}
} catch (Exception e) {
Log.e("UiAutomatorUtil", "executeUiAutomatorDump() 第" + (i+1) + "次尝试失败: " + e.getMessage());
}
// 等待一段时间再重试
if (i < maxRetries - 1) {
Thread.sleep(2000);
}
}
// 如果所有重试都失败,返回最后一次的结果
return result;
}
/** 在顶部输入框输入文本 */
private static boolean inputText(String text) throws Exception {
try {
// 1、调用系统内置的uiautomator工具,以压缩格式输出XML(减少文件体积),保存结果到指定路径的文件
ShellUtil.getExecCmdResult("/system/bin/uiautomator dump --compressed " + fullSensorTestUiXmlPath);
Thread.sleep(1000); // 确保文件写入完成
// 2、解析Xml文本内容以获取输入框坐标(输入框的提示文本(尾部带空格)为 "Only input integer number ") TODO 此处可修改为你的指定文本
UiXmlParser.Rect bounds = UiXmlParser.findBoundsByText(new File(fullSensorTestUiXmlPath), "Only input integer number ");
if (bounds == null) {
Log.e(TAG, "inputText(),未找到输入框控件");
// 按照输入框的文本单位值是"Hz"进行查找
bounds = UiXmlParser.findBoundsByText(new File(fullSensorTestUiXmlPath), "Hz");
if (bounds == null) {
Log.e(TAG, "inputText(),仍然未找到输入框控件");
return false;
}
} else {
Log.i(TAG, "inputText(),已找到输入框控件");
}
// 3、计算中心点并点击,激活输入框
UiXmlParser.Point center = bounds.getCenter();
if (center == null) {
Log.e(TAG, "inputText(),无法计算输入框中心点");
return false;
}
String tapResult = ShellUtil.getExecCmdResult("input tap " + center.x + " " + center.y);
if (tapResult == null) {
Log.e(TAG, "inputText(),点击输入框失败");
return false;
}
Thread.sleep(500); // 等待输入框激活
// 4、输入文本
String inputResult = ShellUtil.getExecCmdResult("input text " + text);
if (inputResult == null) {
Log.e(TAG, "inputText(),输入文本失败");
return false;
}
Log.i(TAG, "inputText(),在输入框中输入文本: " + text);
return true;
} catch (Exception e) {
Log.e(TAG, "inputText(),输入文本时发生异常: " + e.getMessage());
return false;
}
}
}
1.2、UiXmlParser
import android.util.Log;
import org.w3c.dom.Document;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.NodeList;
/**
* Description:XML文件解析工具类
*/
public class UiXmlParser {
private static final String TAG = UiXmlParser.class.getSimpleName();
/** 根据文本内容查找元素 */
public static Rect findBoundsByText(File xmlFile, String targetText) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(xmlFile);
NodeList nodes = doc.getElementsByTagName("node");
for (int i = 0; i < nodes.getLength(); i++) {
org.w3c.dom.Node node = nodes.item(i);
String text = node.getAttributes().getNamedItem("text").getNodeValue();
if (text != null && text.equals(targetText)) {
String bounds = node.getAttributes().getNamedItem("bounds").getNodeValue();
return parseBounds(bounds);
}
}
Log.i(TAG, "findBoundsByText(),根据文本内容查找元素: " + targetText);
} catch (Exception e) {
Log.e(TAG, "findBoundsByText(),Failed to parse xml: " + e.getMessage());
}
return null;
}
/** 解析bounds字符串 */
private static Rect parseBounds(String boundsStr) {
// 示例格式:[100,200][300,400]
String[] parts = boundsStr.replace("[", "").split("]")[0].split(",");
int left = Integer.parseInt(parts[0]);
int top = Integer.parseInt(parts[1]);
parts = boundsStr.split("\\[")[2].replace("]", "").split(",");
int right = Integer.parseInt(parts[0]);
int bottom = Integer.parseInt(parts[1]);
Log.i(TAG, "parseBounds(),解析bounds字符串: " + boundsStr);
return new Rect(left, top, right, bottom);
}
public static class Rect {
public int left, top, right, bottom;
public Rect(int l, int t, int r, int b) {
left = l; top = t; right = r; bottom = b;
}
public Point getCenter() {
return new Point((left + right) / 2, (top + bottom) / 2);
}
}
public static class Point {
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}
2、执行指令工具类
import android.os.Build;
import android.util.Log;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
/**
* 创建时间:2024/2/19
* 功能描述:多种方法执行 adb shell 命令并返回结果
* 注意:使用该类的方法,手机须拥有Root权限
*/
public class ShellUtil {
public static String TAG = ShellUtil.class.getSimpleName();
public static final String COMMAND_SU = "su";
public static final String COMMAND_SH = "sh";
/**
* TODO 方法一:
* 根据系统版本的类型执行命令行,返回执行结果
* @param cmd 命令行字符串
* @return 如果命令行有输出,则返回第一样输出,如果没有输出,则返回空字符串
*/
public static String getExecuteCmdResult(String cmd) {
if (Build.VERSION.INCREMENTAL.toLowerCase().contains("factory") || isUserDebugROM()) {
String userDebugOSResult = executeCmdOnUserDebugOS(cmd);
LOGI("getExecuteCmdResult(),当前系统版本为 factory 或 userdebug 类型,执行结果:" + userDebugOSResult);
return userDebugOSResult;
} else {
String userRootOSResult = executeCmdOnUserRootOS(cmd);
LOGI("getExecuteCmdResult(),当前系统版本为 userroot 类型,执行结果:" + userRootOSResult);
return userRootOSResult;
}
}
/**
* 在 factory 或 userdebug 类型的版本中执行命令行,返回命令行结果
* @param shellCommand
* @return
*/
public static String executeCmdOnUserDebugOS(String shellCommand) {
LOGI("executeCmdOnUserDebugOS(),执行cmd:" + shellCommand);
String line = null;
String stringBuffer = "->";
try {
String[] cmd = new String[]{"/system/bin/sh", "-c", shellCommand};
Process proc = Runtime.getRuntime().exec(cmd);
InputStream inputSt = proc.getInputStream();
BufferedReader reader1 = new BufferedReader(new InputStreamReader(inputSt));
stringBuffer = reader1.readLine();
LOGI("executeCmdOnUserDebugOS(),执行结果:" + stringBuffer);
inputSt.close();
reader1.close();
proc.destroy();
} catch (IOException e) {
LOGE("executeCmdOnUserDebugOS(),关闭流数据时发生IO异常:" + e);
}
return stringBuffer;
}
/**
* 在 userroot 的类型版本中执行命令行,返回命令行结果
* @param cmd 命令行字符串
* @return 如果命令行有输出,则返回第一样输出,如果没有输出,则返回空字符串
*/
public static String executeCmdOnUserRootOS(String cmd) {
LOGI("executeCmdOnUserRootOS(),执行cmd:" + cmd);
Process p = null;
String line = null;
InputStream is = null;
BufferedReader reader = null;
ProcessBuilder pb = null;
String[] cmdStringArray = {"/system/xbin/su", "-c", cmd};
try {
List<String> cmdList = Arrays.asList(cmdStringArray);
pb = new ProcessBuilder().redirectErrorStream(true).command(cmdList);
p = pb.start();
is = p.getInputStream();
reader = new BufferedReader(new InputStreamReader(is));
line = reader.readLine();
LOGI("executeCmdOnUserRootOS(),执行结果:" + line);
} catch (Exception e) {
LOGE("executeCmdOnUserRootOS(),发生异常:" + e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
LOGE("executeCmdOnUserRootOS(),关闭缓冲流时发生IO异常:" + e);
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
LOGE("executeCmdOnUserRootOS(),关闭输入流时发生IO异常:" + e);
}
}
if (p != null) {
p.destroy();
}
}
return ((line == null) ? "" : line);
}
/**
* TODO 方法二:
* 异步执行命令并返回进程引用,支持su/sh权限自动切换
* @param command 要执行的命令
* @return Process 进程引用,可用于控制进程生命周期
* @throws IOException 当无法执行命令时抛出异常
*/
public static Process executeCommandAsRootAsync(String command) throws IOException {
Process process = null;
try {
// 首先尝试使用su权限执行
process = Runtime.getRuntime().exec(new String[]{COMMAND_SU, "-c", command});
LOGI("executeCommandAsRootAsync(),使用su权限执行指令:" + command);
return process;
} catch (IOException e) {
LOGE("executeCommandAsRootAsync(),使用su权限执行失败:" + e.getMessage());
// 如果su权限失败,尝试使用sh权限执行
try {
if (process != null) {
process.destroy();
}
process = Runtime.getRuntime().exec(new String[]{COMMAND_SH, "-c", command});
LOGI("executeCommandAsRootAsync(),使用sh权限执行指令:" + command);
return process;
} catch (IOException e2) {
LOGE("executeCommandAsRootAsync(),使用sh权限执行也失败了:" + e2.getMessage());
if (process != null) {
process.destroy();
}
throw e2; // 抛出sh权限执行失败的异常
}
}
}
/**
* 异步执行命令并返回进程引用和输出结果,支持su/sh权限自动切换
* @param command 要执行的命令
* @param inProcess 用于接收进程引用和输出结果的回调接口
* @throws IOException 当无法执行命令时抛出异常
* @throws InterruptedException 当线程被中断时抛出异常
*/
public static void executeCommandAsRootAsyncWithOutput(String command, InProcess inProcess) throws IOException, InterruptedException {
Process process = null;
try {
// 首先尝试使用su权限执行
process = Runtime.getRuntime().exec(new String[]{COMMAND_SU, "-c", command});
LOGI("executeCommandAsRootAsyncWithOutput(),使用su权限执行指令:" + command);
} catch (IOException e) {
LOGE("executeCommandAsRootAsyncWithOutput(),使用su权限执行失败:" + e.getMessage());
// 如果su权限失败,尝试使用sh权限执行
try {
if (process != null) {
process.destroy();
}
process = Runtime.getRuntime().exec(new String[]{COMMAND_SH, "-c", command});
LOGI("executeCommandAsRootAsyncWithOutput(),使用sh权限执行指令:" + command);
} catch (IOException e2) {
LOGE("executeCommandAsRootAsyncWithOutput(),使用sh权限执行也失败了:" + e2.getMessage());
if (process != null) {
process.destroy();
}
throw e2; // 抛出sh权限执行失败的异常
}
}
// 将进程引用传递给回调
if (inProcess != null) {
inProcess.getProcess(process);
}
// 读取输出流
if (process != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null && !Thread.currentThread().isInterrupted()) {
if (inProcess != null) {
inProcess.parseMsg(line);
}
LOGI("executeCommandAsRootAsyncWithOutput(),执行结果:" + line);
}
reader.close();
}
}
/**
* TODO 方法三:
* 使用不同权限执行adb命令,并返回命令执行结果
* @param command
* @return
*/
public static String executeCommandAsRoot(String command) {
StringBuilder output = new StringBuilder();
// 尝试以 su 权限执行命令
CommandResult suResult = executeCommandWithPermissions(command, COMMAND_SU);
if (suResult.getResultCode() == 0) {
LOGI("executeCommandAsRoot(),su 权限执行成功");
return suResult.getOutput();
} else {
LOGE("executeCommandAsRoot(),su 权限执行失败,error code: " + suResult.getResultCode());
}
// 如果 su 权限执行失败,尝试以 sh 权限执行命令
CommandResult shResult = executeCommandWithPermissions(command, COMMAND_SH);
if (shResult.getResultCode() == 0) {
LOGI("executeCommandAsRoot(),sh 权限执行成功");
return shResult.getOutput();
} else {
LOGE("executeCommandAsRoot(),sh 权限执行失败,error code: " + shResult.getResultCode());
output.append("Error: ").append(shResult.getError());
}
return output.toString();
}
private static CommandResult executeCommandWithPermissions(String command, String permission) {
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
Process process = null;
BufferedReader reader = null;
try {
process = Runtime.getRuntime().exec(new String[]{permission, "-c", command});
processBuilderRedirectErrorStream(process);
LOGI(permission + " --- executeCommandWithPermissions(),执行指令:" + command);
// 读取输出流
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
LOGI("使用 " + permission + "权限 --- executeCommandWithPermissions(),正确结果:" + line);
}
// 读取错误流
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((line = errorReader.readLine()) != null) {
error.append(line).append("\n");
LOGE("使用 " + permission + "权限 --- executeCommandWithPermissions(),错误结果:" + line);
}
int responseCode = process.waitFor();
return new CommandResult(responseCode, output.toString(), error.toString());
} catch (IOException | InterruptedException e) {
LOGE(permission + " --- executeCommandWithPermissions(),执行失败:" + e.getMessage());
error.append("Error: ").append(e.getMessage());
return new CommandResult(-1, output.toString(), error.toString());
} finally {
closeResources(process, reader);
}
}
private static void processBuilderRedirectErrorStream(Process process) {
try {
process.getErrorStream().close(); // 关闭错误流
process.getOutputStream().close(); // 关闭输出流
} catch (IOException e) {
LOGE("processBuilderRedirectErrorStream(),发生异常:" + e.getMessage());
}
}
private static void closeResources(Process process, BufferedReader reader) {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
LOGE("Close BufferedReader Error: " + e.getMessage());
}
}
if (process != null) {
process.destroy();
}
}
/**
* TODO 方法四:
* 执行adb命令,并返回执行结果
* @param cmd
* @return
* @throws IOException
* @throws InterruptedException
*/
public static String getExecCmdResult(String cmd) throws IOException, InterruptedException {
StringBuilder result = new StringBuilder();
DataOutputStream lDataOutputStream = null;
DataInputStream lDataInputStream = null;
Process lProcess = null;
try {
lProcess = Runtime.getRuntime().exec(COMMAND_SU);
} catch (IOException pE) {
lProcess = Runtime.getRuntime().exec(COMMAND_SH);
}
lDataOutputStream = new DataOutputStream(lProcess.getOutputStream());
lDataInputStream = new DataInputStream(lProcess.getInputStream());
BufferedReader lBufferedReader = new BufferedReader(new InputStreamReader(lDataInputStream));
lDataOutputStream.writeBytes(cmd + "\n");
LOGI("getExecCmdResult(),execute cmd: " + cmd);
lDataOutputStream.writeBytes("exit\n");
lDataOutputStream.flush();
String line = null;
while ((line = lBufferedReader.readLine()) != null && !Thread.currentThread().isInterrupted()) {
result.append(line);
LOGI("getExecCmdResult(),execute result:" + result);
}
lProcess.waitFor();
if (lDataInputStream != null) {
lDataOutputStream.close();
}
if (lDataInputStream != null) {
lDataInputStream.close();
}
LOGI(result.toString());
return result.toString();
}
/**
* TODO 方法五:
* 解析命令执行结果
*/
public static void parseCmdResult(String cmd, InCmdMsg pInCmdMsg) throws IOException, InterruptedException {
DataOutputStream lDataOutputStream = null;
DataInputStream lDataInputStream = null;
Process lProcess = null;
try {
lProcess = Runtime.getRuntime().exec(COMMAND_SU);
} catch (IOException pE) {
lProcess = Runtime.getRuntime().exec(COMMAND_SH);
}
lDataOutputStream = new DataOutputStream(lProcess.getOutputStream());
lDataInputStream = new DataInputStream(lProcess.getInputStream());
BufferedReader lBufferedReader = new BufferedReader(new InputStreamReader(lDataInputStream));
lDataOutputStream.writeBytes(cmd + "\n");
LOGI("parseCmdResult(),execute cmd: " + cmd);
lDataOutputStream.writeBytes("exit\n");
lDataOutputStream.flush();
String line = null;
while ((line = lBufferedReader.readLine()) != null && !Thread.currentThread().isInterrupted()) {
if (pInCmdMsg!= null){
pInCmdMsg.parseMsg(line);
}
}
lProcess.waitFor();
if (lDataInputStream != null) {
lDataOutputStream.close();
}
if (lDataInputStream != null) {
lDataInputStream.close();
}
}
/**
* TODO 方法六:
* 解析命令执行结果
*/
public static void parseCmdProcess(String cmd, InProcess pInProcess) throws IOException, InterruptedException {
DataOutputStream lDataOutputStream = null;
DataInputStream lDataInputStream = null;
Process lProcess = null;
try {
lProcess = Runtime.getRuntime().exec(COMMAND_SU);
} catch (IOException pE) {
lProcess = Runtime.getRuntime().exec(COMMAND_SH);
}
if (pInProcess!= null){
pInProcess.getProcess(lProcess);
}
lDataOutputStream = new DataOutputStream(lProcess.getOutputStream());
lDataInputStream = new DataInputStream(lProcess.getInputStream());
BufferedReader lBufferedReader = new BufferedReader(new InputStreamReader(lDataInputStream));
lDataOutputStream.writeBytes(cmd + "\n");
LOGI("parseCmdResult(),execute cmd: " + cmd);
lDataOutputStream.writeBytes("exit\n");
lDataOutputStream.flush();
String line = null;
while ((line = lBufferedReader.readLine()) != null && !Thread.currentThread().isInterrupted()) {
if (pInProcess!= null){
pInProcess.parseMsg(line);
}
}
lProcess.waitFor();
if (lDataInputStream != null) {
lDataOutputStream.close();
}
if (lDataInputStream != null) {
lDataInputStream.close();
}
}
/**
* TODO 方法七:
* 执行命令,并把结果写入文件
*/
public static void getExecCmdResultToFile(String cmd, String fileName, boolean append) throws IOException, InterruptedException {
DataOutputStream lDataOutputStream = null;
DataInputStream lDataInputStream = null;
Process lProcess = null;
try {
lProcess = Runtime.getRuntime().exec(COMMAND_SU);
} catch (IOException pE) {
lProcess = Runtime.getRuntime().exec(COMMAND_SH);
}
File lFile = new File(fileName);
if (!lFile.exists()) {
lFile.createNewFile();
}
OutputStream lOutputStream = null;
try {
lOutputStream = new FileOutputStream(lFile, append);
} catch (FileNotFoundException pE) {
}
lDataOutputStream = new DataOutputStream(lProcess.getOutputStream());
lDataInputStream = new DataInputStream(lProcess.getInputStream());
BufferedReader lBufferedReader = new BufferedReader(new InputStreamReader(lDataInputStream));
lDataOutputStream.writeBytes(cmd + "\n");
LOGI("exec: " + cmd);
lDataOutputStream.writeBytes("exit\n");
lDataOutputStream.flush();
String line = null;
while ((line = lBufferedReader.readLine()) != null && !Thread.currentThread().isInterrupted()) {
lOutputStream.write(line.getBytes());
lOutputStream.write("\r\n".getBytes());
}
lProcess.waitFor();
if (lDataInputStream != null) {
lDataOutputStream.close();
}
if (lDataInputStream != null) {
lDataInputStream.close();
}
}
/** 是否为 userdebug 类型版本 */
public static boolean isUserDebugROM() {
String fingerPrint = executeCmdOnUserDebugOS("getprop ro.product.build.fingerprint");
if (fingerPrint.toLowerCase().contains("userdebug")) {
LOGI("isUserDebugROM():true");
return true;
} else {
LOGI("isUserDebugROM():false");
return false;
}
}
public static void LOGI(String msg) {
Log.i(TAG, msg);
}
public static void LOGE(String msg) {
Log.e(TAG, msg);
}
public static interface InCmdMsg{
void parseMsg(String msg);
}
public static interface InProcess{
void getProcess(Process pProcess);
void parseMsg(String msg);
}
// 定义 CommandResult 类
public static class CommandResult {
private final int resultCode;
private final String output;
private final String error;
public CommandResult(int resultCode, String output, String error) {
this.resultCode = resultCode;
this.output = output;
this.error = error;
}
public int getResultCode() {
return resultCode;
}
public String getOutput() {
return output;
}
public String getError() {
return error;
}
}
}
3、调用示例
import android.util.Log;
import 你的包名.UiAutomatorUtil;
import 你的包名.UiXmlParser;
import 你的包名.util.ShellUtil;
import java.io.File;
/**
* Description:自动化测试操作类
*/
public class TestAutomator {
private static final String TAG = TestAutomator.class.getSimpleName();
private static final String testUiXmlPath = "/sdcard/UiDump.xml";
private static final long TEST_DURATION = 5 * 1000; // 运行时长
/** APP 自动化测试操作 */
public static boolean runStressTest() {
Log.i(TAG, "runStressTest(), 自动化测试操作,已开始");
try {
// 1、启动APP
ShellUtil.getExecCmdResult("am start -n 应用包名/启动Activity");
Thread.sleep(2000); // 等待启动
// 2、点击"Consumer IR"
boolean consumerIRResult = UiAutomatorUtil.clickByText(TAG, "Consumer IR", testUiXmlPath);
if (!consumerIRResult) {
Log.e(TAG, "runStressTest(),未能找到或点击'Consumer IR'按钮");
return false;
}
Thread.sleep(1000); // 等待跳转
// 3、在输入框输入 "100"
boolean inputResult = UiAutomatorUtil.inputText("100");
if (!inputResult) {
Log.e(TAG, "runStressTest(),未能在输入框中输入文本");
return false;
}
Thread.sleep(500); // 等待输入完成
// 4、点击"Power"
boolean powerResult = UiAutomatorUtil.clickByText(TAG,"Power", testUiXmlPath);
if (!powerResult) {
Log.e(TAG, "runStressTest(),未能找到或点击'Power'按钮");
return false;
}
// 5、等待测试完成
Thread.sleep(TEST_DURATION);
// 6、退出应用
ShellUtil.getExecCmdResult("am force-stop 应用包名");
Log.i(TAG, "runStressTest(),APP 自动化测试操作,已完成");
return true;
} catch (Exception e) {
Log.e(TAG, "runStressTest(),APP 自动化测试操作时发生异常: " + e.getMessage());
return false;
}
}
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)