In the official documentation here: https://google.github.io/android-testing-support-library/docs/rules/index.html, it says:
"This rule provides functional testing of a single activity. The activity under test will be launched before each test annotated with @Test and before any method annotated with @Before. It will be terminated after the test is completed and all methods annotated with @After are finished. The Activity under Test can be accessed during your test by calling ActivityTestRule#getActivity()."
Technically yes, the Activity is being terminated. But there doesn't seem to be any guarantee as to when this will happen. E.g. it won't necessarily happen before it's created again for the next test.
In some of my tests, I need to rely on the fragments OnDestroy or OnDetach being called after each test, before the next test starts. I have listeners that need to be cleared and recreated.
If onDestroy from the previous test is called after OnResume in the current test, then the callback is cleared and the view doesn't get updated and the test fails.
If onDestroy from the previous test is not called at all, then the callback from the current test will be referring to the wrong instance. Again the view will not get updated and the test will fail.
Edit: I've now solved part 2. See workarounds section below. However if someone can answer part one by citing an official resource then I'd be happy to accept that answer. That's what I'm really asking here. The second part was just a bonus if someone had some ideas.
If you would like to see this behaviour it will only take a few moments. Create a new project with an Activity like this:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
and a test class like this:
@RunWith(AndroidJUnit4.class)
@LargeTest
public class EspressoLifecycleTest {
@Rule
public ActivityTestRule<MainActivity> mActivityRule =
new ActivityTestRule<>(MainActivity.class);
@Test
public void test1() {
}
@Test
public void test2() {
}
@Test
public void test3() {
}
@Test
public void test4() {
}
}
Put breakpoints on the OnResume and OnDestroy methods and run the test suite in debug mode.
Do this a few times and notice that the order the Activity life cycle methods are called is not consistent. E.g. it might call OnResume twice in a row, and then call OnDestroy once, and then OnResume twice again, and then OnDestroy three times, or any other combination you can think of. Of course it always starts with at least one OnResume. Sometimes it doesn't even call OnDestroy if it's at the very end, but that's fine. What's not fine is that my tests are flaky because of this unpredicatable order.
I'm aware that this might be intentional and there could be a simple way to deal with it, I'm just not lucky enough to have found it. Please if you know what it is, post the answer here. I don't care how dumb my question might be in hindsight, I've spent a LOT of time on this problem. It's almost always something simple so I'm prepared to be embarrassed by the answer.
Using onPause over OnDestroy has the side effect of being called when I startActivityForResult, but without calling onResume again in the background fragment while in tablet mode. I'm exploring ways to make this work but no solution as yet.
Edit: onPause ended up with the same problem - which is partly why I was using onDetach in the first place. Ultimately, there are times when I don't want to detach the listeners until the fragment is destroyed.
This leads me to my next idea which worked! Hooray! Up until now I was creating a callback for the calling Activity, for the thing it was asking for, only if that specific callback didn't exist. It turns out this was a bad idea. I did that so I could limit the number of callbacks to the exact number required. The motivation was sound but the implementation required all this callback clearing. The solution is to recreate every callback when ever it's called from the fragment. Don't create it if it's null, always create it and replace whatever was there before. Now there's no need to clear them at all (AFAIK).
Record UI interactionsClick Run > Record Espresso Test. In the Select Deployment Target window, choose the device on which you want to record the test. If necessary, create a new Android Virtual Device. Click OK.
Espresso created by Google is a native framework for Android automated testing. The tool is a part of the Android SDK and is easy to use for native mobile development. Thanks to Espresso, you can create tests that are close to the Android app's logic.
Espresso is a testing framework that helps developers write automation test cases for user interface (UI) testing. It has been developed by Google and aims to provide a simple yet powerful framework. It allows both black-box testing as well as testing of individual components during development cycles.
It's a bug: http://b.android.com/201513
I use fork work around it: https://github.com/shazam/fork
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With