Android中JUnit4 UiAutomator测试进程启动后迅速终止且无异常
问题
在Android环境下使用JUnit4编写的UiAutomator测试用例,执行时仅打印少量System.out输出后就迅速完成,调试模式下表现一致。Logcat显示进程已结束,但未捕获到任何异常,代码编译无错误;即使附加调试器测试,仍执行失败。
测试代码如下:
/** * Basic sample for unbundled UiAutomator. */ @RunWith(AndroidJUnit4.class) @SdkSuppress(minSdkVersion = 18) public class UITestPOC { private static final String BASIC_SAMPLE_PACKAGE = "com.test.basic"; private static final int LAUNCH_TIMEOUT = 50000; private static final String STRING_TO_BE_TYPED = "UiAutomator"; private UiDevice mDevice; @Before public void startMainActivityFromHomeScreen() { // Initialize UiDevice instance System.out.println("before device init"); Instrumentation instr = InstrumentationRegistry.getInstrumentation(); mDevice = UiDevice.getInstance(instr); // Start from the home screen mDevice.pressHome(); System.out.println("after press home"); // Wait for launcher final String launcherPackage = getLauncherPackageName(); assertThat(launcherPackage, notNullValue()); mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); // Launch the blueprint app Context context = getApplicationContext(); final Intent intent = context.getPackageManager() .getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear out any previous instances context.startActivity(intent); // Wait for the app to appear mDevice.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT); } private String getLauncherPackageName() { // Create launcher Intent final Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); // Use PackageManager to get the launcher package name PackageManager pm = getApplicationContext().getPackageManager(); ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); return resolveInfo.activityInfo.packageName; } @Test public void testChangeText_sameActivity() { // Type text and then press the button. mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "editTextUserInput")) .setText(STRING_TO_BE_TYPED); mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "changeTextBt")) .click(); // Verify the test is displayed in the Ui UiObject2 changedText = mDevice .wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "textToBeChanged")), 500 /* wait 500ms */); assertThat(changedText.getText(), is(equalTo(STRING_TO_BE_TYPED))); } }
排查与解决方案
检查测试配置与依赖
确认测试模块build.gradle中UiAutomator和JUnit依赖配置正确:androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' androidTestImplementation 'androidx.test.ext:junit:1.1.5'同时确保
AndroidManifest.xml声明了必要权限:<uses-permission android:name="android.permission.GET_TASKS"/>显式检查
@Before方法中的隐性失败点
代码中assertThat(launcherPackage, notNullValue())断言失败时,会直接终止测试但无明确日志。替换为显式空值检查并抛出异常:if (launcherPackage == null) { throw new RuntimeException("无法获取Launcher包名"); }启动目标应用前,先确认Intent不为空:
if (intent == null) { throw new RuntimeException("未找到目标应用启动Intent,检查包名:" + BASIC_SAMPLE_PACKAGE); }优化等待逻辑与日志输出
把测试方法中控件等待时间从500ms延长至3000ms,避免因控件加载慢导致查找失败;同时用Log.d替代System.out,确保日志能正常输出:Log.d("UITestPOC", "before device init"); // ... UiObject2 changedText = mDevice .wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "textToBeChanged")), 3000);校验目标应用控件ID
确认被测应用中editTextUserInput、changeTextBt、textToBeChanged的控件ID与测试代码完全一致,避免因ID拼写错误导致控件查找失败。
内容的提问来源于stack exchange,提问作者Hemanth
相关产品推荐
相关产品推荐

