Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test saving and restoring state of an android activity with Espresso?

Is there a way of testing the save and restore state code of an activity programmatically ? I mean doing this :

How to test code built to save/restore Lifecycle of an Activity? but in an automated way.

I have tested activity.recreate() method which is almost what I am searching, but in fact it does not reset the fields of my activity like if I was killing the process. So my test can pass even if I don't implement the restoring things in my onCreate method (since my fields are unchanged...).

I am currently playing with Espresso v2 and I was wondering if this could be possible maybe by playing with the InstrumentationRegistry.getInstrumentation() ?

like image 227
JojoCT Avatar asked Oct 03 '15 19:10

JojoCT


People also ask

How do I test onSaveInstanceState?

To test onSaveInstanceState and onRestoreInstanceState you can use either the SetAlwaysFinish tool (see link below) or the DevTools app included with the emulator. Both of these apps use a hidden setting called AlwaysFinish which is part of the ActivityManagerNative class to change the behavior of the Android OS.

How can I save an activity state using the Save instance state?

Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.

How do you test activity?

To test an activity, you use the ActivityTestRule class provided by the Android Testing Support Library. 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.


3 Answers

The solution is to use the activity.recreate() method BUT do not forget to follow this by an assertion which waits for an idle state. My problem with my first attempt was that the test I was writing was like :

instrumentation.runOnMainSync(new Runnable() {
    @Override
    public void run() {
        activity.recreate();
    }
});
assertThat(activityTestRule.getActivity().getXXX()).isNull();

Where XXX was a field that I expected to be null when no save/restore state handling had been implemented. But that was not the case because my assertion was not waiting for the recreation task to be completed.

So in my situation, my problem was solved when I simply add an espresso assertion which does the job, for example by verifiying that the TextView which displayed the XXX field was empty.

Finally, thanks to the UI thread synchronization provided by Espresso, my test which can assert on my activity save/restore state missing implementation can be written like :

instrumentation.runOnMainSync(new Runnable() {
    @Override
    public void run() {
        activity.recreate();
    }
});
onView(withText("a string depending on XXX value")).check(doesNotExist());

Note that the rotation solution suggested does the job either, but can be much slower than activity.recreate() when we just want to test the activity lifecycle. And in my case it was not relevant since my activity was not implemented for a landscape orientation.

like image 78
JojoCT Avatar answered Oct 07 '22 14:10

JojoCT


You can rotate the screen and verify that the state is saved and restored properly.

private void rotateScreen() {
  Context context = InstrumentationRegistry.getTargetContext();
  int orientation 
    = context.getResources().getConfiguration().orientation;

  Activity activity = activityRule.getActivity();
  activity.setRequestedOrientation(
      (orientation == Configuration.ORIENTATION_PORTRAIT) ?
          ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : 
          ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

Full example: http://blog.sqisland.com/2015/10/espresso-save-and-restore-state.html

like image 30
chiuki Avatar answered Oct 07 '22 12:10

chiuki


The testing tools offered by Android now offer a means of writing UI tests that can recreate an activity to test the save and restore flow. See the Recreate the activity section within the Test your app's activities Android Developers documentation page. An example of the syntax – taken from that page – is the following:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        val scenario = launchActivity<MyActivity>()
        scenario.recreate()
    }
}
like image 1
Adil Hussain Avatar answered Oct 07 '22 14:10

Adil Hussain