From a41160229ddf57c913b4d6eea1601737220c3e6f Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Thu, 17 Dec 2020 22:58:31 +0100 Subject: [PATCH] Implement basic EspressoUI test. --- build.gradle | 1 + .../dennisguse/opentracks/EspressoUITest.java | 168 ++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 src/androidTest/java/de/dennisguse/opentracks/EspressoUITest.java diff --git a/build.gradle b/build.gradle index b4b3e4fae..bc663acbb 100644 --- a/build.gradle +++ b/build.gradle @@ -86,6 +86,7 @@ android { } dependencies { + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0-alpha02' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1' implementation 'androidx.appcompat:appcompat:1.2.0' diff --git a/src/androidTest/java/de/dennisguse/opentracks/EspressoUITest.java b/src/androidTest/java/de/dennisguse/opentracks/EspressoUITest.java new file mode 100644 index 000000000..c3322ed4d --- /dev/null +++ b/src/androidTest/java/de/dennisguse/opentracks/EspressoUITest.java @@ -0,0 +1,168 @@ +package de.dennisguse.opentracks; + +import android.view.MotionEvent; +import android.view.View; + +import androidx.test.espresso.UiController; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.ViewInteraction; +import androidx.test.espresso.action.MotionEvents; +import androidx.test.ext.junit.rules.ActivityScenarioRule; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.LargeTest; +import androidx.test.rule.GrantPermissionRule; + +import com.google.android.material.tabs.TabLayout; + +import org.hamcrest.Matcher; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class EspressoUITest { + + @Rule + public ActivityScenarioRule mActivityTestRule = new ActivityScenarioRule<>(TrackListActivity.class); + + @Rule + public GrantPermissionRule mGrantPermissionRule = GrantPermissionRule.grant("android.permission.ACCESS_FINE_LOCATION"); + + @LargeTest + @Test + public void record_pause_resume_stop() { + { + // TrackListActivity: start recording + ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_controller_record)); + trackControllerRecordButton.perform(click()); + } + { + // TrackRecordingActivity + ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_controller_record)); + ViewInteraction trackControllerStopButton = onView(withId(R.id.track_controller_stop)); + + // wait; stay recording + trackControllerRecordButton.perform(waitFor(5000)); + + //pause + trackControllerRecordButton.perform(veryLongTouch(1600)); + + // wait; stay paused + trackControllerRecordButton.perform(waitFor(1000)); + + // resume + trackControllerRecordButton.perform(click()); + + // wait; stay recording + trackControllerRecordButton.perform(waitFor(1000)); + + // stop; + trackControllerStopButton.perform(veryLongTouch(1600)); + } + } + + @LargeTest + @Test + public void record_move_through_tabs() { + { + // TrackListActivity: start recording + ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_controller_record)); + trackControllerRecordButton.perform(click()); + } + { + // TrackRecordingActivity + ViewInteraction tabLayout = onView(withId(R.id.track_detail_activity_tablayout)); + ViewInteraction trackControllerStopButton = onView(withId(R.id.track_controller_stop)); + + tabLayout.perform(selectTabAtIndex(1)); + tabLayout.perform(waitFor(1000)); + + tabLayout.perform(selectTabAtIndex(2)); + tabLayout.perform(waitFor(1000)); + + tabLayout.perform(selectTabAtIndex(3)); + tabLayout.perform(waitFor(1000)); + + tabLayout.perform(selectTabAtIndex(0)); + tabLayout.perform(waitFor(1000)); + + // stop + trackControllerStopButton.perform(veryLongTouch(1600)); + } + } + + private static ViewAction veryLongTouch(final int duration_ms) { + return new ViewAction() { + @Override + public String getDescription() { + return "Perform long touch."; + } + + @Override + public Matcher getConstraints() { + return isDisplayed(); + } + + @Override + public void perform(UiController uiController, final View view) { + // Get view absolute position + int[] location = new int[2]; + view.getLocationOnScreen(location); + + // Offset coordinates by view position + float[] coordinates = new float[]{location[0] + 1, location[1] + 1}; + + // Send down event, pause, and send up + MotionEvent down = MotionEvents.sendDown(uiController, coordinates, new float[]{1f, 1f}).down; + uiController.loopMainThreadForAtLeast(duration_ms); + MotionEvents.sendUp(uiController, down, coordinates); + } + }; + } + + private static ViewAction waitFor(final long duration_ms) { + return new ViewAction() { + + @Override + public String getDescription() { + return "Wait for milliseconds."; + } + + @Override + public Matcher getConstraints() { + return isDisplayed(); + } + + @Override + public void perform(UiController uiController, final View view) { + uiController.loopMainThreadForAtLeast(duration_ms); + } + }; + } + + private static ViewAction selectTabAtIndex(final int index) { + return new ViewAction() { + @Override + public String getDescription() { + return "Selecting tab."; + } + + @Override + public Matcher getConstraints() { + return isDisplayed(); + } + + @Override + public void perform(UiController uiController, View view) { + TabLayout tabLayout = (TabLayout) view; + tabLayout.getTabAt(index).select(); + } + }; + } +}