tests: dismiss dialogs in the emulator with back button before run

The ARM emulator can show ANRs for 'system' on boot, so that dialog needs
to be dismissed before the Espresso tests can happen.

https://android.googlesource.com/platform/frameworks/testing/+/master/uiautomator_test_libraries/src/com/android/uiautomator/common/UiWatchers.java
This commit is contained in:
Hans-Christoph Steiner 2018-08-14 18:24:30 +02:00
parent 990d05dc0f
commit 9d8232472f
2 changed files with 168 additions and 0 deletions

View File

@ -9,6 +9,9 @@ import android.support.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector;
import android.util.Log;
import android.view.View;
import org.fdroid.fdroid.views.BannerUpdatingRepos;
@ -71,6 +74,15 @@ public class MainActivityEspressoTest {
e.printStackTrace();
}
SystemAnimations.disableAll(InstrumentationRegistry.getTargetContext());
// dismiss the ANR or any other system dialogs that might be there
UiObject button = new UiObject(new UiSelector().text("Wait").enabled(true));
try {
button.click();
} catch (UiObjectNotFoundException e) {
Log.d(TAG, e.getLocalizedMessage());
}
new UiWatchers().registerAnrAndCrashWatchers();
}
@AfterClass

View File

@ -0,0 +1,156 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fdroid.fdroid;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.UiWatcher;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@SuppressWarnings("MemberName")
public class UiWatchers {
private static final String LOG_TAG = UiWatchers.class.getSimpleName();
private final List<String> mErrors = new ArrayList<String>();
/**
* We can use the UiDevice registerWatcher to register a small script to be executed when the
* framework is waiting for a control to appear. Waiting may be the cause of an unexpected
* dialog on the screen and it is the time when the framework runs the registered watchers.
* This is a sample watcher looking for ANR and crashes. it closes it and moves on. You should
* create your own watchers and handle error logging properly for your type of tests.
*/
public void registerAnrAndCrashWatchers() {
UiDevice.getInstance().registerWatcher("ANR", new UiWatcher() {
@Override
public boolean checkForCondition() {
UiObject window = new UiObject(new UiSelector().className(
"com.android.server.am.AppNotRespondingDialog"));
String errorText = null;
if (window.exists()) {
try {
errorText = window.getText();
} catch (UiObjectNotFoundException e) {
Log.e(LOG_TAG, "dialog gone?", e);
}
onAnrDetected(errorText);
postHandler("Wait");
return true; // triggered
}
return false; // no trigger
}
});
// class names may have changed
UiDevice.getInstance().registerWatcher("ANR2", new UiWatcher() {
@Override
public boolean checkForCondition() {
UiObject window = new UiObject(new UiSelector().packageName("android")
.textContains("isn't responding."));
if (window.exists()) {
String errorText = null;
try {
errorText = window.getText();
} catch (UiObjectNotFoundException e) {
Log.e(LOG_TAG, "dialog gone?", e);
}
onAnrDetected(errorText);
postHandler("Wait");
return true; // triggered
}
return false; // no trigger
}
});
UiDevice.getInstance().registerWatcher("CRASH", new UiWatcher() {
@Override
public boolean checkForCondition() {
UiObject window = new UiObject(new UiSelector().className(
"com.android.server.am.AppErrorDialog"));
if (window.exists()) {
String errorText = null;
try {
errorText = window.getText();
} catch (UiObjectNotFoundException e) {
Log.e(LOG_TAG, "dialog gone?", e);
}
onCrashDetected(errorText);
postHandler("OK");
return true; // triggered
}
return false; // no trigger
}
});
UiDevice.getInstance().registerWatcher("CRASH2", new UiWatcher() {
@Override
public boolean checkForCondition() {
UiObject window = new UiObject(new UiSelector().packageName("android")
.textContains("has stopped"));
if (window.exists()) {
String errorText = null;
try {
errorText = window.getText();
} catch (UiObjectNotFoundException e) {
Log.e(LOG_TAG, "dialog gone?", e);
}
onCrashDetected(errorText);
postHandler("OK");
return true; // triggered
}
return false; // no trigger
}
});
Log.i(LOG_TAG, "Registed GUI Exception watchers");
}
public void onAnrDetected(String errorText) {
mErrors.add(errorText);
}
public void onCrashDetected(String errorText) {
mErrors.add(errorText);
}
public void reset() {
mErrors.clear();
}
public List<String> getErrors() {
return Collections.unmodifiableList(mErrors);
}
/**
* Current implementation ignores the exception and continues.
*/
public void postHandler(String buttonText) {
// TODO: Add custom error logging here
String formatedOutput = String.format("UI Exception Message: %-20s\n", UiDevice
.getInstance().getCurrentPackageName());
Log.e(LOG_TAG, formatedOutput);
UiObject buttonOK = new UiObject(new UiSelector().text(buttonText).enabled(true));
// sometimes it takes a while for the OK button to become enabled
buttonOK.waitForExists(5000);
try {
buttonOK.click();
} catch (UiObjectNotFoundException e) {
e.printStackTrace();
}
}
}