From 1137fd4b5668c918515d5d0bdfb009c3e160d4c6 Mon Sep 17 00:00:00 2001 From: Jake Wharton Date: Tue, 14 Jul 2015 20:18:44 -0400 Subject: [PATCH] Add simple UI Automator tests. --- .github/workflows/build.yaml | 11 +- build.gradle | 6 +- gradle.properties | 3 + process-phoenix/build.gradle | 7 ++ .../src/androidTest/AndroidManifest.xml | 15 +++ .../processphoenix/ProcessPhoenixTest.java | 105 ++++++++++++++++++ 6 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 process-phoenix/src/androidTest/AndroidManifest.xml create mode 100644 process-phoenix/src/androidTest/java/com/jakewharton/processphoenix/ProcessPhoenixTest.java diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4db26a7..3c0e271 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -10,7 +10,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: macos-latest steps: - uses: actions/checkout@v2.3.4 @@ -21,7 +21,14 @@ jobs: distribution: 'zulu' java-version: 8 - - run: ./gradlew build + - run: ./gradlew build assembleAndroidTest + + - name: Run Tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 24 + # The tests require the sample to be installed. + script: ./gradlew installDebug connectedCheck - run: ./gradlew uploadArchives if: ${{ github.ref == 'refs/heads/trunk' && github.repository == 'JakeWharton/ProcessPhoenix' }} diff --git a/build.gradle b/build.gradle index 2649cbc..fb65cbc 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,10 @@ allprojects { } ext { - minSdkVersion = 11 + minSdkVersion = 14 compileSdkVersion = 30 + + androidxTestRunner = 'androidx.test:runner:1.3.0' + androidxTestRules = 'androidx.test:rules:1.3.0' + androidxTestUiAutomator = 'androidx.test.uiautomator:uiautomator:2.2.0' } diff --git a/gradle.properties b/gradle.properties index 2b3dc69..39dffd6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,3 +14,6 @@ POM_LICENCE_DIST=repo POM_DEVELOPER_ID=jakewharton POM_DEVELOPER_NAME=Jake Wharton + +android.useAndroidX=true +android.enableJetifier=false diff --git a/process-phoenix/build.gradle b/process-phoenix/build.gradle index 719ab94..f41a79c 100644 --- a/process-phoenix/build.gradle +++ b/process-phoenix/build.gradle @@ -1,10 +1,17 @@ apply plugin: 'com.android.library' +dependencies { + androidTestImplementation rootProject.ext.androidxTestRunner + androidTestImplementation rootProject.ext.androidxTestRules + androidTestImplementation rootProject.ext.androidxTestUiAutomator +} + android { compileSdkVersion rootProject.ext.compileSdkVersion defaultConfig { minSdkVersion rootProject.ext.minSdkVersion + testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } compileOptions { diff --git a/process-phoenix/src/androidTest/AndroidManifest.xml b/process-phoenix/src/androidTest/AndroidManifest.xml new file mode 100644 index 0000000..981e459 --- /dev/null +++ b/process-phoenix/src/androidTest/AndroidManifest.xml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/process-phoenix/src/androidTest/java/com/jakewharton/processphoenix/ProcessPhoenixTest.java b/process-phoenix/src/androidTest/java/com/jakewharton/processphoenix/ProcessPhoenixTest.java new file mode 100644 index 0000000..b73dcf0 --- /dev/null +++ b/process-phoenix/src/androidTest/java/com/jakewharton/processphoenix/ProcessPhoenixTest.java @@ -0,0 +1,105 @@ +package com.jakewharton.processphoenix; + +import android.app.Instrumentation; +import android.app.KeyguardManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.PowerManager; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.content.Context.KEYGUARD_SERVICE; +import static android.content.Context.POWER_SERVICE; +import static android.content.Intent.CATEGORY_LAUNCHER; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.os.PowerManager.ACQUIRE_CAUSES_WAKEUP; +import static android.os.PowerManager.FULL_WAKE_LOCK; +import static android.os.PowerManager.ON_AFTER_RELEASE; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +public final class ProcessPhoenixTest { + private static final String PROCESS_ID = "Process ID: "; + private static final String EXTRA_TEXT = "Extra Text: "; + private static final String TARGET_PACKAGE = "com.jakewharton.processphoenix.sample"; + + private final Context context = InstrumentationRegistry.getTargetContext(); + private final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + private final UiDevice device = UiDevice.getInstance(instrumentation); + + private PowerManager.WakeLock wakeLock; + + @Before public void launchSample() { + // Wake up the screen. + PowerManager power = (PowerManager) context.getSystemService(POWER_SERVICE); + wakeLock = power.newWakeLock(FULL_WAKE_LOCK | ACQUIRE_CAUSES_WAKEUP | ON_AFTER_RELEASE, "test"); + wakeLock.acquire(); + + // Unlock the device so that the tests can input keystrokes. + KeyguardManager keyguard = (KeyguardManager) context.getSystemService(KEYGUARD_SERVICE); + keyguard.newKeyguardLock("test").disableKeyguard(); + + // Launch the sample app. + PackageManager pm = context.getPackageManager(); + Intent intent = pm.getLaunchIntentForPackage(TARGET_PACKAGE); + if (intent == null) { + throw new AssertionError("ProcessPhoenix Sample not installed."); + } + intent.addCategory(CATEGORY_LAUNCHER); + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + waitForWindow(); + } + + private void waitForWindow() { + assertTrue(device.waitForWindowUpdate(TARGET_PACKAGE, SECONDS.toMillis(15))); + } + + @After public void tearDown() { + wakeLock.release(); + } + + @Test public void triggerRebirthCreatesNewProcess() throws UiObjectNotFoundException { + UiObject originalObject = device.findObject(new UiSelector().textStartsWith(PROCESS_ID)); + int originalId = Integer.parseInt(originalObject.getText().substring(PROCESS_ID.length())); + + device.findObject(new UiSelector().text("Restart Process")).click(); + waitForWindow(); + + UiObject newObject = device.findObject(new UiSelector().textStartsWith(PROCESS_ID)); + int newId = Integer.parseInt(newObject.getText().substring(PROCESS_ID.length())); + + assertNotEquals(originalId, newId); + } + + @Test public void triggerRebirthWithIntentCreatesNewProcessUsingIntent() + throws UiObjectNotFoundException { + UiObject originalObject = device.findObject(new UiSelector().textStartsWith(PROCESS_ID)); + int originalId = Integer.parseInt(originalObject.getText().substring(PROCESS_ID.length())); + + device.findObject(new UiSelector().text("Restart Process with Intent")).click(); + waitForWindow(); + + UiObject newObject = device.findObject(new UiSelector().textStartsWith(PROCESS_ID)); + int newId = Integer.parseInt(newObject.getText().substring(PROCESS_ID.length())); + + assertNotEquals(originalId, newId); + + UiObject extraObject = device.findObject(new UiSelector().textStartsWith(EXTRA_TEXT)); + String extraText = extraObject.getText().substring(EXTRA_TEXT.length()); + + assertEquals("Hello!", extraText); + } +}