diff --git a/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java b/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java index 5f4871240..7fd5a57b9 100644 --- a/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java +++ b/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java @@ -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 diff --git a/app/src/androidTest/java/org/fdroid/fdroid/UiWatchers.java b/app/src/androidTest/java/org/fdroid/fdroid/UiWatchers.java new file mode 100644 index 000000000..1458653e8 --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/fdroid/UiWatchers.java @@ -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 mErrors = new ArrayList(); + + /** + * 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 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(); + } + } +} \ No newline at end of file