Merge pull request #4841 from damoasda/fix-MainActivityTest-testAddFeed

Fix MainActivityTest.testAddFeed() timeout failure
This commit is contained in:
ByteHamster 2021-01-12 11:01:17 +01:00 committed by GitHub
commit 9fd24ab8aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 20 deletions

View File

@ -3,8 +3,10 @@ package de.test.antennapod;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.preference.PreferenceManager;
import androidx.test.espresso.NoMatchingViewException;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.espresso.PerformException;
import androidx.test.espresso.UiController;
@ -15,6 +17,9 @@ import androidx.test.espresso.contrib.RecyclerViewActions;
import androidx.test.espresso.util.HumanReadables;
import androidx.test.espresso.util.TreeIterables;
import android.view.View;
import junit.framework.AssertionFailedError;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@ -33,6 +38,7 @@ import java.util.concurrent.TimeoutException;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
@ -57,7 +63,7 @@ public class EspressoTestUtils {
@Override
public String getDescription() {
return "wait for a specific view for" + millis + " millis.";
return "wait for a specific view for " + millis + " millis.";
}
@Override
@ -87,6 +93,33 @@ public class EspressoTestUtils {
};
}
/**
* Wait until a certain view becomes visible, but at the longest until the timeout.
* Unlike {@link #waitForView(Matcher, long)} it doesn't stick to the initial root view.
*
* @param viewMatcher The view to wait for.
* @param timeoutMillis Maximum waiting period in milliseconds.
* @throws Exception Throws an Exception in case of a timeout.
*/
public static void waitForViewGlobally(@NonNull Matcher<View> viewMatcher, long timeoutMillis) throws Exception {
long startTime = System.currentTimeMillis();
long endTime = startTime + timeoutMillis;
do {
try {
onView(viewMatcher).check(matches(isDisplayed()));
// no Exception thrown -> check successful
return;
} catch (NoMatchingViewException | AssertionFailedError ignore) {
// check was not successful "not found" -> continue waiting
}
//noinspection BusyWait
Thread.sleep(50);
} while (System.currentTimeMillis() < endTime);
throw new Exception("Timeout after " + timeoutMillis + " ms");
}
/**
* Perform action of waiting for a specific view id.
* https://stackoverflow.com/a/30338665/
@ -113,7 +146,7 @@ public class EspressoTestUtils {
}
/**
* Clear all app databases
* Clear all app databases.
*/
public static void clearPreferences() {
File root = InstrumentationRegistry.getInstrumentation().getTargetContext().getFilesDir().getParentFile();

View File

@ -2,16 +2,14 @@ package de.test.antennapod.ui;
import android.app.Activity;
import android.content.Intent;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.espresso.Espresso;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.robotium.solo.Solo;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.test.antennapod.EspressoTestUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@ -20,6 +18,12 @@ import org.junit.runner.RunWith;
import java.io.IOException;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.test.antennapod.EspressoTestUtils;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.replaceText;
@ -28,18 +32,17 @@ import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.contrib.ActivityResultMatchers.hasResultCode;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static de.test.antennapod.EspressoTestUtils.clickPreference;
import static de.test.antennapod.EspressoTestUtils.openNavDrawer;
import static de.test.antennapod.EspressoTestUtils.waitForView;
import static de.test.antennapod.EspressoTestUtils.waitForViewGlobally;
import static org.hamcrest.Matchers.allOf;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* User interface tests for MainActivity
* User interface tests for MainActivity.
*/
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {
@ -48,19 +51,19 @@ public class MainActivityTest {
private UITestUtils uiTestUtils;
@Rule
public IntentsTestRule<MainActivity> mActivityRule = new IntentsTestRule<>(MainActivity.class, false, false);
public IntentsTestRule<MainActivity> activityRule = new IntentsTestRule<>(MainActivity.class, false, false);
@Before
public void setUp() throws IOException {
EspressoTestUtils.clearPreferences();
EspressoTestUtils.clearDatabase();
mActivityRule.launchActivity(new Intent());
activityRule.launchActivity(new Intent());
uiTestUtils = new UITestUtils(InstrumentationRegistry.getInstrumentation().getTargetContext());
uiTestUtils.setup();
solo = new Solo(InstrumentationRegistry.getInstrumentation(), mActivityRule.getActivity());
solo = new Solo(InstrumentationRegistry.getInstrumentation(), activityRule.getActivity());
}
@After
@ -71,6 +74,7 @@ public class MainActivityTest {
@Test
public void testAddFeed() throws Exception {
// connect to podcast feed
uiTestUtils.addHostedFeedData();
final Feed feed = uiTestUtils.hostedFeeds.get(0);
openNavDrawer();
@ -78,9 +82,14 @@ public class MainActivityTest {
onView(withId(R.id.addViaUrlButton)).perform(scrollTo(), click());
onView(withId(R.id.urlEditText)).perform(replaceText(feed.getDownload_url()));
onView(withText(R.string.confirm_label)).perform(scrollTo(), click());
// subscribe podcast
Espresso.closeSoftKeyboard();
waitForViewGlobally(withText(R.string.subscribe_label), 15000);
onView(withText(R.string.subscribe_label)).perform(click());
onView(isRoot()).perform(waitForView(withId(R.id.butShowSettings), 5000));
// wait for podcast feed item list
waitForViewGlobally(withId(R.id.butShowSettings), 15000);
}
@Test
@ -100,7 +109,7 @@ public class MainActivityTest {
onView(allOf(withId(R.id.toolbar), isDisplayed())).check(
matches(hasDescendant(withText(R.string.subscriptions_label))));
solo.goBack();
assertThat(mActivityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
assertThat(activityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
}
@Test
@ -113,7 +122,7 @@ public class MainActivityTest {
solo.goBackToActivity(MainActivity.class.getSimpleName());
solo.goBack();
solo.goBack();
assertTrue(((MainActivity)solo.getCurrentActivity()).isDrawerOpen());
assertTrue(((MainActivity) solo.getCurrentActivity()).isDrawerOpen());
}
@Test
@ -127,7 +136,7 @@ public class MainActivityTest {
solo.goBack();
solo.goBack();
solo.goBack();
assertThat(mActivityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
assertThat(activityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
}
@Test
@ -142,7 +151,7 @@ public class MainActivityTest {
solo.goBack();
onView(withText(R.string.yes)).perform(click());
Thread.sleep(100);
assertThat(mActivityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
assertThat(activityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
}
@Test
@ -155,6 +164,6 @@ public class MainActivityTest {
solo.goBackToActivity(MainActivity.class.getSimpleName());
solo.goBack();
solo.goBack();
assertThat(mActivityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
assertThat(activityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
}
}