10

When start my android app first start FirstActivity. When I click button on FirstActivity than start AddTraderActivity. If I press button "START REQUEST" in AddTraderActivity then I call:

setResult(RESULT_OK);
finish();

As result AddTraderActivity is destroy and show FirstActivity. Nice.

Now I want to write Espresso's tests for AddTraderActivityTest . Here tests:

@RunWith(AndroidJUnit4::class)
@SmallTest
class AddTraderActivityTest {

    @get:Rule
    var addTraderActivity: IntentsTestRule<AddTraderActivity> =
        IntentsTestRule(AddTraderActivity::class.java)

    @Test
    fun toolBarHeight() {
        onView(withId(R.id.toolBar))
            .check(matches(withHeightResId(R.dimen.tool_bar_height)))
    }

    @Test
    fun buttonStartTextUppercase() {
        onView(withId(R.id.startButton))
            .check(matches(withTextUppercaseResId(R.string.start)))
    }
}

As result when I start this tests, then start ONLY AddTraderActivity and tests success pass. Nice.

Now I want to write test for click on button "START REQUEST"

Here test:

@Test
fun pressButtonStartProgressBarDisplayed() {
    onView(withId(R.id.baseTextInputEditText)).perform(typeText("BASE_TEST"))
    onView(withId(R.id.quoteTextInputEditText)).perform(typeText("QUOTE_TEST"))
    onView(withId(R.id.startButton)).perform(click())

    onView(withId(R.id.containerProgressBarLayout)).check(matches(isDisplayed()))
}

As result when test run and press button "START REQUEST" I get the next error:

Testing started at 16:05 ...

$ adb shell am instrument -w -r   -e debug false -e class 'com.myproject.AddTraderActivityTest#pressButtonStartProgressBarDisplayed' com.myproject.debug.test/androidx.test.runner.AndroidJUnitRunner
Client not ready yet..
Started running tests

java.lang.RuntimeException: No activities found. Did you forget to launch the activity by calling getActivity() or startActivitySync or similar?
at androidx.test.espresso.base.RootViewPicker.waitForAtLeastOneActivityToBeResumed(RootViewPicker.java:169)
at androidx.test.espresso.base.RootViewPicker.get(RootViewPicker.java:83)
at androidx.test.espresso.ViewInteractionModule.provideRootView(ViewInteractionModule.java:77)
at androidx.test.espresso.ViewInteractionModule_ProvideRootViewFactory.provideRootView(ViewInteractionModule_ProvideRootViewFactory.java:35)
at androidx.test.espresso.ViewInteractionModule_ProvideRootViewFactory.get(ViewInteractionModule_ProvideRootViewFactory.java:24)
at androidx.test.espresso.ViewInteractionModule_ProvideRootViewFactory.get(ViewInteractionModule_ProvideRootViewFactory.java:10)
at androidx.test.espresso.base.ViewFinderImpl.getView(ViewFinderImpl.java:62)
at androidx.test.espresso.ViewInteraction$2.call(ViewInteraction.java:276)
at androidx.test.espresso.ViewInteraction$2.call(ViewInteraction.java:268)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

I get this error because in stack has no activity FirstActivity, because my test not start it. So the question is. How I can ISOLATE test only AddTraderActivity?

Alexei
  • 14,350
  • 37
  • 121
  • 240

2 Answers2

4

This problem can happen if you migrate from ActivityTestRule to ActivityScenarioRule (or ActivityScenario) and you are trying to test an Activity that has the following code in its onCreate() method:

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // Workaround the Android bug of multiple Activity task stacks when
  // the app is launched from the Google Play Store. See:
  // https://issuetracker.google.com/issues/36941942
  // https://stackoverflow.com/questions/4341600/multiple-instances-of-activity-from-google-play-launch
  // https://stackoverflow.com/questions/19545889/app-restarts-rather-than-resumes
  if (!isTaskRoot() &&
      getIntent().hasCategory(Intent.CATEGORY_LAUNCHER) &&
      Intent.ACTION_MAIN.equals(getIntent().getAction())) {
    finish();
    return;
  }

  ...
}

This code worked fine with ActivityTestRule. But it does not work with ActivityScenarioRule or ActivityScenario, because it causes errors when the test tries to launch the Activity:

The problem happens because the test will launch the Activity and then immediately close it in onCreate(). So you must remove the entire if block when using ActivityScenarioRule or ActivityScenario, or add an additional boolean parameter in the if clause, to check if you are running a UI test.

Mr-IDE
  • 7,051
  • 1
  • 53
  • 59
3

Ideally, you should probably use a separate class for testing separate activity.

But, if you need, you can isolate rules per method using following approach

[EDIT] (Caution: You can NOT use @get:Rule annotation anymore):

@Test
public void myTest() {
      // launch desired activity
      var firstActivity: IntentsTestRule<FirstActivity> = IntentsTestRule(FirstActivity::class.java)
      firstActivity.launchActivity(Intent())

      // add tests
      onView(withId(R.id.baseTextInputEditText)).perform(typeText("BASE_TEST"))
      onView(withId(R.id.quoteTextInputEditText)).perform(typeText("QUOTE_TEST"))
}
  • Now I get error: java.lang.IllegalStateException: #init was called twice in a row. Make sure to call #release after every #init – Alexei Apr 09 '19 at 09:53
  • 1
    Yeah, Man I'm sorry I should have been specific, You can **NOT** use `@get:Rule` annotation anymore. It is getting called for your second method as well. Updating answer. –  Apr 10 '19 at 09:00
  • I try this : Rule JvmField var jsonViewActivity = ActivityTestRule(JsonViewActivity::class.java) Intents.init() intended(hasComponent(JsonViewActivity::class.java.getName())), but I get error: androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: Wanted to match 1 intents. Actually matched 0 intents. – Alexei Apr 11 '19 at 14:54
  • what is IntentsTestRule? – NehaK Jan 16 '21 at 13:12
  • what do you mean "You can NOT use `@get:Rule`"? I'm using it right now – Chisko Oct 14 '22 at 23:39
  • @Chisko I meant OP cannot use `@get:Rule` anymore, as OP was asking to launch activity specifically, and `@get:Rule` would auto trigger `AddTraderActivity`. So OP should remove it. –  Jul 29 '23 at 03:31