Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

On second test getActivity() never returns

I have a couple of simple tests, like assertNotNull(mActivity); (I'm reading M.D.Torres "Android Application Testing Guide"). The activity under test runs okay. Every single test runs okay as well. But if I run several tests at once on the second test getActivity() never returns. No errors in logcat (last line "Starting Intent ..."), no nothing. Debugging doesn't help much either, if I step into getActivity() it complains that there is no source code available.
Another test project - ActivityTesting from Google runs okay even with several tests, so Eclipse is configured right.
Did anybody ever encounter something like that?

like image 316
Art Shayderov Avatar asked Jan 15 '12 16:01

Art Shayderov


2 Answers

I recreated test project once more (like "clean room") and it worked. Then I compared two projects and found the culprit. It was empty teardown:

protected void tearDown() throws Exception {
}

If I remove it, all tests run green. If I paste it back, second test hangs. Now I would like to read the explanation and ready to mark it as answer.

Edit: I should be calling super.tearDown() at the end of the tearDown method. Sorry for bothering everybody.

like image 158
Art Shayderov Avatar answered Sep 28 '22 18:09

Art Shayderov


I used ActivityInstrumentationTestCase2 to test an Activity using ExoPlayer and correct resource clean up as well. As the clean up and final checks are the same for all the tests, I thought that tearDown() is a good place to implement them. All the tests run separately without any problem, but when I run multiple tests, sometimes getActivity() did not return. My tearDown() implemented various things:

  • check state of activity (various assert() calls)
  • check state of player (various assert() calls)
  • clean up player resources manually (calling close() and release())
  • setActivity(null) (this caused the trouble)
  • super.tearDown()

I tried all the suggested workarounds like overriding getActivity() and using the other methods of instrumentation to create and clean up the activity. These methods did not help.

And lots of debugging showed, that with above scenario the onDestory() of the activity of the previous test can overlap with the onCreate() of the activity of the next test. So the logs showed the life cycle events in this order:

test1.getActivity();
test1.tearDown() called;
test1.tearDown() over;
test2.getActivity()
test2.onCreate();
test1.onStop(); --> why is this late?
test1.onDestroy(); --> why is this late?
test2.tearDown() called;
test2.tearDown() over;
test3.getActiviy() --> this should call test3.onCreate, but did not and never returned.

This happens even when the test cases are implemented in separate ActivityInstrumentationTestCase2 classes/files. And the fist time this overlap does not cause trouble yet, so 2 tests are always OK, but running 3 tests in any order that result in this overlap causes the 3rd call to getActivity() to never return.

I tried everything like calling onPause() + onStop() + onDestroy() manually using the instrumentation, introducing really long sleep periods between tests, force clearing the activity of the instrumentationTestCase, reordering checks of my tearDown, but nothing helped. Finally, I accidentally removed setActivity( null) before my checks, and the life cycle events got correctly ordered:

test1.tearDown() called;
test1.onStop();
test1.onDestroy();
test1.tearDown() over;
test2.getActivity()
test2.onCreate();
...

So what really made the difference in my case: do not call ActivityTestCase.setActivity(). This causes the super.tearDown() not to call the life cycle events of the activity directly, clean up will happen later and cause trouble.

like image 21
Habib Avatar answered Sep 28 '22 17:09

Habib