12

I have multiple UI tests. When I run a single test, everything is OK. But if I run a batch of them (as a part of CI build) test fail, because tests that go first change the state of the application, and the next tests are affected by those changes. (Since the app is not getting killed).

I tried getActivity().finish() in tearDown().
Tried solo.finalize() which does the same actually.

Is there a way to have a fresh app at the beginning of each test run? (Using Robotium).
And is there a way to programmatically kill the app at the end of a test?
I'm using ActivityInstrumentationTestCase2 with Robotium

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Taras
  • 488
  • 6
  • 21
  • That may well slow down your tests a bit. Have you tried to just reset your application back to a known state as sort of a setup process rather than actually killing it and reinitializing it? – squawknull Oct 21 '11 at 15:13
  • The properties (part of the application state) of the application that my test affected by are initialized at startup. So there's no way i can do that without changing how the app works. It wonders me that the whole test concept is about having isolated runs, butin android testing this isolation is compromised, at least UI-tesing-wise. I thinks this should be considered as a fundamental problem, but i can't seem to find any info about that problem – Taras Oct 22 '11 at 06:47
  • I agree. I got exactly the same problem : single tests work pretty well with robotium, but when you try to have 2 tests in the same instrumentation run, then you get a second test hanging forever. tried also to finalize and finish all activites but nothing works. Robotium should adress this issue. Their examples have always one and only one test class. – Snicolas Dec 08 '11 at 16:43

7 Answers7

5

Or just add solo.finishOpenedActivities();

BlackHatSamurai
  • 23,275
  • 22
  • 95
  • 156
2

Not exactly sure of the nature of your test suite but I had problems running multiple "fresh start" tests and hanging on second test. My problem related to spawned activities and was resovled by launching the activity with FLAG_ACTIVITY_CLEAR_TOP - of course this clears the stack but I think that's what you want?

    Intent i = new Intent();
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    setActivityIntent(i);
    solo = new Solo(getInstrumentation(), getActivity());
joedev
  • 65
  • 5
  • This did it for me, thanks! Also, and since I have a confirmation dialogbox to exit my application solo.finishOpenedActivities() won't do it, have to use solo.goBack() and hit proper button in the dialogbox. –  Mar 29 '13 at 17:50
1

Why not adding an adhoc way of "killing" the app, depending on the specific app you're testing? For example, depending on your application activity depth, "press back 3 times" or something similar could be good enough.

You could add that in the tearDown method of your tests superclass, so that it's ran after each of your tests.

You should think about your Robotium tests not as normal unit-tests (they're not!), but as user-cases, acceptance-tests. So if you want to close the app, do in these tests exactly what you would expect the user to do to close the app.

Guillaume
  • 22,694
  • 14
  • 56
  • 70
  • I ll try that asap and give you some feedback. – Snicolas Dec 13 '11 at 15:07
  • Unit test runner just crashes when app under test stops [echo] testing package : story.album [exec] [exec] story.album.Album1Story: [exec] INSTRUMENTATION_RESULT: shortMsg=Process crashed. [exec] INSTRUMENTATION_CODE: 0 – Snicolas Dec 13 '11 at 15:24
  • I have done so. Needed to update a lot of tests. But works okay. One drawback - If tests change you need to make sure this "clean up" code is updated as well – Taras Dec 14 '11 at 12:48
1

The causes of the problem are:

  1. There is no Android API to get a list of all the activities in a stack.
  2. A workaround for (1) is to use an ActivityMonitor to keep track of each Activity that starts.
  3. Robotium uses the workaround, but it sets up its ActivityMonitor AFTER your ActivityInstrumentationTestCase2 test case starts its activity, i.e.:

    Activity activity = getActivity();
    Solo solo = new Solo(getInstrumentation(), activity);
    

If your activity-under-test is a forwarding activity, then it is likely starting the destination activity before Solo registers its ActivityMonitor. Solo.finishOPenedActivities() relies on the list that it collected from its ActivityMonitor.

As per the @Guillaume answer, I call this method from the test case or from tearDown():

private void backOutToHome() {
    boolean more = true;
    while(more) {
        try {
            getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
        } catch (SecurityException e) { // Done, at Home.
            more = false;
        }
    }
}
Community
  • 1
  • 1
cdhabecker
  • 1,693
  • 1
  • 14
  • 23
0

You can try to delete super.tearDown();

zys
  • 1,306
  • 3
  • 18
  • 37
0

My solution:

    @Override
    public void tearDown() throws Exception {

        solo.finishOpenedActivities();

        super.tearDown();
    }
Cícero Moura
  • 2,027
  • 1
  • 24
  • 36
0

If you run your build with maven or ant (Robotium is a convenience wrapper for JUnit-Tests), there is an option to fork a new process for every test class or even test case. This provides clean environment, but slows down test execution.

I personally prefer to stick with vanilla Junit / TestNG and utilize mocking (with jMockit) to assure proper interaction beween my code and android. See sample here:

https://github.com/ko5tik/andject/blob/master/src/test/java/de/pribluda/android/andject/ViewInjectionTest.java

Konstantin Pribluda
  • 12,329
  • 1
  • 30
  • 35
  • actually one must use adb shell am instrument to run tests on android, not junit. There does not seem to be anyway to fork processes for each test via adb – Snicolas Dec 13 '11 at 15:46