如何在Android Appium测试的@BeforeScenario中选择指定appPackage与appActivity
针对多应用测试场景的Capabilities配置优化方案
你当前在@BeforeScenario中通过配置Desired Capabilities来指定启动的App Package和Activity的方案完全可行,尤其是在startActivity因权限限制无法使用的情况下,这确实是最稳妥的替代方案。
不过为了让你的测试框架更灵活地支持多个应用的测试场景,这里有几个实用的优化建议:
1. 抽离应用配置信息,避免硬编码
把每个应用的APP_PACKAGE和APP_ACTIVITY抽成枚举类统一管理,新增应用时不用修改测试逻辑代码,只需要添加新的配置项即可:
// 定义Android应用的枚举类,集中管理所有应用的核心配置 public enum AndroidApp { NOTEPAD("com.example.notepad", ".MainActivity"), CALCULATOR("com.android.calculator2", ".Calculator"), MESSAGES("com.android.mms", ".ui.ConversationList"); // 可按需扩展更多应用 private final String appPackage; private final String appActivity; AndroidApp(String appPackage, String appActivity) { this.appPackage = appPackage; this.appActivity = appActivity; } // Getter方法 public String getAppPackage() { return appPackage; } public String getAppActivity() { return appActivity; } }
2. 通过外部参数动态指定要启动的应用
可以通过系统属性、测试标签或者测试上下文来动态传递目标应用,不用每次修改代码里的判断逻辑就能切换不同应用的测试:
修改你的@BeforeScenario方法,比如通过系统属性来指定要测试的应用:
@BeforeScenario public void beforeScenario() throws MalformedURLException { DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); desiredCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "device"); desiredCapabilities.setCapability(MobileCapabilityType.UDID, "L2N4C19924005752"); // 从系统属性获取目标应用,启动测试时可传入 -Dtest.app=CALCULATOR 快速切换 String targetAppKey = System.getProperty("test.app", "NOTEPAD"); AndroidApp targetApp = AndroidApp.valueOf(targetAppKey.toUpperCase()); if (localAndroid) { logger.info("Starting local Android app: " + targetApp.name()); // 从枚举中自动获取对应的Package和Activity desiredCapabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, targetApp.getAppPackage()); desiredCapabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, targetApp.getAppActivity()); } // 其他Capabilities配置保持不变 desiredCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "uiautomator2"); desiredCapabilities.setCapability(MobileCapabilityType.NO_RESET, true); desiredCapabilities.setCapability(MobileCapabilityType.FULL_RESET, false); desiredCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 300); desiredCapabilities.setCapability("unicodeKeyboard", false); desiredCapabilities.setCapability("appWaitDuration", 30); desiredCapabilities.setCapability("resetKeyboard", false); URL url = new URL("http://localhost:4723/wd/hub"); appiumDriver = new AndroidDriver(url, desiredCapabilities); selector = SelectorFactory.createElementHelper(localAndroid ? SelectorType.ANDROID : SelectorType.IOS); appiumDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); appiumFluentWait = new FluentWait(appiumDriver) .withTimeout(8, TimeUnit.SECONDS) .pollingEvery(350, TimeUnit.MILLISECONDS) .ignoring(NoSuchElementException.class); }
3. 适配不同应用的状态重置需求
因为你设置了NO_RESET = true,App的本地状态会被保留。如果不同应用的测试需要干净的初始状态,可以给枚举类添加状态重置配置,动态调整Capabilities:
// 给枚举类新增是否需要重置状态的属性 public enum AndroidApp { NOTEPAD("com.example.notepad", ".MainActivity", true), // 需要完全重置 CALCULATOR("com.android.calculator2", ".Calculator", false); // 保留状态 private final String appPackage; private final String appActivity; private final boolean needFullReset; AndroidApp(String appPackage, String appActivity, boolean needFullReset) { this.appPackage = appPackage; this.appActivity = appActivity; this.needFullReset = needFullReset; } // 新增Getter方法 public boolean isNeedFullReset() { return needFullReset; } } // 在配置Capabilities时动态设置 desiredCapabilities.setCapability(MobileCapabilityType.NO_RESET, !targetApp.isNeedFullReset()); desiredCapabilities.setCapability(MobileCapabilityType.FULL_RESET, targetApp.isNeedFullReset());
这样你的测试框架就能更高效地支持多应用的测试场景,后续维护和扩展也会轻松很多。
内容的提问来源于stack exchange,提问作者Silas Hayri
相关产品推荐
相关产品推荐

