You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java的Selenium中执行ADB命令并在AWS Device Farm运行JUnit测试

在Java Appium中执行ADB命令、部署到AWS Device Farm并获取性能数据

我来帮你一步步解决这几个问题——在Java Appium测试里执行ADB命令、部署到AWS Device Farm,还有获取应用的内存和CPU使用率,结合你的现有代码来调整:


一、在测试中执行ADB命令(推荐用Appium原生方式)

在Appium环境里,直接调用系统Runtime.exec()执行ADB命令在本地没问题,但到了AWS DeviceFarm这种云端环境会有依赖问题。更稳妥的是用Appium提供的mobile: shell扩展命令,它能直接在设备端执行shell命令(相当于adb shell),不需要依赖本地ADB。

核心代码示例

你可以封装两个工具方法,用来执行ADB命令获取性能数据:

// 获取CPU使用率(过滤目标应用包名)
private String getCpuUsage(String packageName) {
    try {
        Map<String, Object> params = new HashMap<>();
        params.put("command", String.format("top -n 1 | grep %s", packageName));
        return (String) driver.executeScript("mobile: shell", params);
    } catch (Exception e) {
        e.printStackTrace();
        return "获取CPU数据失败";
    }
}

// 获取内存使用率(提取Total PSS指标,反映实际占用内存)
private String getMemoryUsage(String packageName) {
    try {
        Map<String, Object> params = new HashMap<>();
        params.put("command", String.format("dumpsys meminfo %s", packageName));
        String memInfo = (String) driver.executeScript("mobile: shell", params);
        // 正则提取关键数据
        Pattern pattern = Pattern.compile("Total PSS:\\s+(\\d+)");
        Matcher matcher = pattern.matcher(memInfo);
        if (matcher.find()) {
            return String.format("Total PSS: %s KB", matcher.group(1));
        }
        return memInfo;
    } catch (Exception e) {
        e.printStackTrace();
        return "获取内存数据失败";
    }
}

二、获取目标应用的内存和CPU使用率

把上面的工具方法整合到你的测试流程里,比如在每次操作前后打印性能数据,方便对比:
在你的test()方法循环中,加入这些代码:

String timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS").format(new Date());
// 操作前获取性能数据
System.out.println(timestamp + " 操作前CPU使用率: " + getCpuUsage("com.androidappname.app"));
System.out.println(timestamp + " 操作前内存使用率: " + getMemoryUsage("com.androidappname.app"));

// 这里放你的原有操作代码(比如滑动、点击等)

// 操作后再次获取性能数据
timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS").format(new Date());
System.out.println(timestamp + " 操作后CPU使用率: " + getCpuUsage("com.androidappname.app"));
System.out.println(timestamp + " 操作后内存使用率: " + getMemoryUsage("com.androidappname.app"));

三、将JUnit测试部署到AWS Device Farm

AWS Device Farm支持Appium Java JUnit测试,需要做几个关键调整:

1. 调整Appium Driver初始化代码

Device Farm会自动提供Appium服务,不需要硬编码本地URL,改成兼容本地和云端的写法:

@Before
public void setUp() throws Exception {
    System.out.println("capabilities creation start.........");
    DesiredCapabilities capabilities = new DesiredCapabilities();
    // 移除硬编码的deviceName和version,Device Farm会自动匹配选中的设备
    capabilities.setCapability("platformName", "Android");
    capabilities.setCapability("appPackage","com.androidappname.app");
    capabilities.setCapability("appActivity","com.androidappname.app.views.activities.SplashScreenActivity");
    capabilities.setCapability("newCommandTimeout", "450000");
    capabilities.setCapability("gpsEnabled",true);
    System.out.println("android driver loading start.........");
    
    // 兼容本地和Device Farm的Appium URL
    String appiumUrl = System.getenv("APPIUM_URL");
    if (appiumUrl == null) {
        appiumUrl = "http://127.0.0.1:4723/wd/hub";
    }
    driver = new AndroidDriver(new URL(appiumUrl), capabilities);
    driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
}

2. 打包测试代码为Fat Jar

Device Farm需要包含所有依赖的可执行JAR,用Maven的shade插件打包,在pom.xml中添加配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <!-- 如果不需要主类可以去掉这行 -->
                                <mainClass>macdjtest</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

执行mvn package就能得到包含所有依赖的Fat Jar。

3. 在AWS Device Farm中部署测试

  1. 登录AWS控制台,进入Device Farm服务,创建新项目。
  2. 选择Android平台,上传你的应用APK。
  3. 选择Appium Java JUnit作为测试类型,上传你打包好的测试Fat Jar。
  4. 选择测试设备池(公共设备池或私有设备),启动测试。
  5. 测试完成后,在控制台查看测试结果、日志和性能数据。

四、整合后的完整测试代码

import io.appium.java_client.android.AndroidDriver;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebDriverWait;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;

import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class macdjtest {
    static AndroidDriver driver;
    Dimension size;
    int count=0;
    private static final String PACKAGE_NAME = "com.androidappname.app";

    @Before
    public void setUp() throws Exception {
        System.out.println("capabilities creation start.........");
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("platformName", "Android");
        capabilities.setCapability("appPackage", PACKAGE_NAME);
        capabilities.setCapability("appActivity","com.androidappname.app.views.activities.SplashScreenActivity");
        capabilities.setCapability("newCommandTimeout", "450000");
        capabilities.setCapability("gpsEnabled",true);
        System.out.println("android driver loading start.........");
        
        // 兼容本地和Device Farm的Appium URL
        String appiumUrl = System.getenv("APPIUM_URL");
        if (appiumUrl == null) {
            appiumUrl = "http://127.0.0.1:4723/wd/hub";
        }
        driver = new AndroidDriver(new URL(appiumUrl), capabilities);
        driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
    }

    @After
    public void tearDown() throws Exception {
        if (driver != null) {
            driver.quit();
        }
    }

    // 获取CPU使用率
    private String getCpuUsage() {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("command", String.format("top -n 1 | grep %s", PACKAGE_NAME));
            return (String) driver.executeScript("mobile: shell", params);
        } catch (Exception e) {
            e.printStackTrace();
            return "获取CPU数据失败";
        }
    }

    // 获取内存使用率(Total PSS)
    private String getMemoryUsage() {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("command", String.format("dumpsys meminfo %s", PACKAGE_NAME));
            String memInfo = (String) driver.executeScript("mobile: shell", params);
            Pattern pattern = Pattern.compile("Total PSS:\\s+(\\d+)");
            Matcher matcher = pattern.matcher(memInfo);
            if (matcher.find()) {
                return String.format("Total PSS: %s KB", matcher.group(1));
            }
            return "内存详情:\n" + memInfo;
        } catch (Exception e) {
            e.printStackTrace();
            return "获取内存数据失败";
        }
    }

    @Test
    public void test() throws Exception {
        System.out.println("Inside the test method");
        size = driver.manage().window().getSize();
        int startx = (int) (size.width * 0.85);
        int endx = (int) (size.width * 0.20);
        int starty = size.height / 2;
        System.out.println(size);
        WebDriverWait wait = new WebDriverWait(driver, 240);
        
        for(int i=1;i<=10;i=i+1) {
            driver.resetApp();
            String timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS").format(new Date());
            System.out.println(timestamp + " Startsession");
            
            // 操作前获取性能数据
            System.out.println(timestamp + " 操作前CPU使用率: " + getCpuUsage());
            System.out.println(timestamp + " 操作前内存使用率: " + getMemoryUsage());
            
            //Selecting
            wait.until(ExpectedConditions.elementToBeClickable(By.id("com.androidappname.app:id/sit_url")));
            driver.findElementById("com.androidappname.app:id/sit_url").click();
            
            wait.until(ExpectedConditions.elementToBeClickable(By.id("com.androidappname.app:id/txt_title")));
            //clicking on the next 3 times
            System.out.println("Find the text next");
            for(int i1=1;i1<=3;i1++) {
                driver.findElementById("com.androidappname.app:id/txt_next").click();
            }
            
            System.out.println("Explore as guest");
            wait.until(ExpectedConditions.elementToBeClickable(By.id("com.androidappname.app:id/txt_guest")));
            Thread.sleep(500);
            driver.findElementById("com.androidappname.app:id/txt_guest").click();
            
            System.out.println("Access Granting for the location");
            wait.until(ExpectedConditions.elementToBeClickable(By.id("com.android.packageinstaller:id/permission_allow_button")));
            driver.findElementById("com.android.packageinstaller:id/permission_allow_button").click();
            
            wait.until(ExpectedConditions.elementToBeClickable(By.id("com.androidappname.app:id/ivYasHeader")));
            System.out.println("Home Page Screen");
            
            for(int j=1;j<=4;j++) {
                System.out.println("Swipe");
                driver.swipe(startx, starty, endx, starty, 3000);
                Thread.sleep(500);
            }
            
            Thread.sleep(500);
            wait.until(ExpectedConditions.elementToBeClickable(By.id("com.androidappname.app:id/ivYasHeader")));
            driver.findElementById("com.androidappname.app:id/footerYasImage").click();
            
            Thread.sleep(500);
            wait.until(ExpectedConditions.elementToBeClickable(By.id("android:id/button2")));
            driver.findElementById("android:id/button2").click();
            
            wait.until(ExpectedConditions.elementToBeClickable(By.id("com.androidappname.app:id/whats_on_tv")));
            driver.findElementById("com.androidappname.app:id/navigation_whatson").click();
            
            Thread.sleep(500);
            wait.until(ExpectedConditions.elementToBeClickable(By.id("com.androidappname.app:id/whats_on_tv")));
            
            driver.findElementById("com.androidappname.app:id/navigation_yas_guide").click();
            Thread.sleep(500);
            
            wait.until(ExpectedConditions.elementToBeClickable(By.id("com.androidappname.app:id/icon_menu")));
            driver.findElementById("com.androidappname.app:id/icon_menu").click();
            Thread.sleep(500);
            
            System.out.println("Clicking on menu Icon");
            System.out.print(count++);
            
            // 操作后获取性能数据
            timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS").format(new Date());
            System.out.println(timestamp + " 操作后CPU使用率: " + getCpuUsage());
            System.out.println(timestamp + " 操作后内存使用率: " + getMemoryUsage());
        }
    }
}

五、注意事项

  1. 命令兼容性:不同Android版本的top命令输出格式可能有差异,如果grep不到结果,可以换成ps -eo %cpu,cmd | grep %s来获取CPU数据。
  2. 测试超时:Device Farm有测试总时长限制,确保newCommandTimeout设置合理,避免测试中途超时。
  3. 日志查看:测试完成后,在Device Farm控制台的“Logs”标签下可以查看你打印的性能数据和测试日志。

内容的提问来源于stack exchange,提问作者Rajat Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:53:25