Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Activity lifecycle unit testing

Tags:

In an activity unit test how can I emulate the activity lifecycle events.

I can call the instrumentation's callActivityOn... methods on the existing activity, but how do I trigger activity recreation so that the activity's OnCreate gets the bundle with saved state

like image 499
mfeingold Avatar asked Feb 22 '12 18:02

mfeingold


2 Answers

I have found that this code cause new Activity to be created:

myActivity.finish();
setActivity(null);
myActivity = getActivity();

But this does not cause onSaveInstanceState to be called. So for example to test if activity is propely created after view orientation change such test should do it:

private mInstrumentation = getInstrumentation();
...
final Bundle outState = new Bundle();
mInstrumentation.callActivityOnSaveInstanceState(mActivity, outState);
mActivity.finish();
setActivity(null);
mActivity = getActivity();
runTestOnUiThread(new Thread() {
    @Override
    public void run() {
        mInstrumentation.callActivityOnRestoreInstanceState(mActivity, outState);
    }
});
like image 194
Michal Avatar answered Dec 08 '22 08:12

Michal


Do not follow the state management test example : {dead link}

myActivity.finish();
myActivity = getActivity();

ActivityInstrumentationTestCase2.getActivity() starts the Activity the first time you call it, but then it simply returns that same Activity in each subsequent call in the test case. Thus, you are still looking at the Activity that you finished.

After you finish the first Activity, you need to start a new one from the test. You can use InstrumentationTestCase.launchActivity(), for example.

As another example, I've written a test that pushes a button in ActivityA that launches ActivityB for-result; the test then immediately kills ActivityA (via an orientation change, but finish() would work, too), and then the test gets a handle to the new ActivityA that the system creates when ActivityB is done and sends its result. The trick there was to have the test add an Instrumentation.ActivityMonitor and then have that monitor wait for the system to start the new ActivityA and give the test a handle to it.

EDIT 2/23/2012 cdhabecker, Adding reproducible code:

public class VerboseActivity extends Activity {
    public final static String TAG = "Verbose";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "onCreate() " + (Activity)this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity5);
    }
    @Override
    protected void onDestroy() {
        Log.i(TAG, "onDestroy().");
        super.onDestroy();
    }
}

Test case: (the sleep() calls give the activity lots of time to respond)

public class VerboseTest extends
        ActivityInstrumentationTestCase2<VerboseActivity> {

    Activity myActivity = null;

    public VerboseTest() {
        super("com.scanillion.demo", VerboseActivity.class);
    }

    public void test_01() {
        String TAG = "test_01";
        myActivity = getActivity();
        Log.i(TAG, "A getActivity()=" + myActivity);
        myActivity.finish();
        try {
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
        }
        myActivity = getActivity();
        Log.i(TAG, "B getActivity()=" + myActivity);
        try {
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
        }
    }
}

Log:

02-23 21:25:37.689: I/Verbose(17747): onCreate() com.scanillion.demo.VerboseActivity@43ba3360
02-23 21:25:38.159: I/ActivityManager(67): Displayed activity com.scanillion.demo/.VerboseActivity: 526 ms (total 526 ms)
02-23 21:25:38.180: I/test_01(17747): A getActivity()=com.scanillion.demo.VerboseActivity@43ba3360
02-23 21:25:38.540: I/Verbose(17747): onDestroy().
02-23 21:25:43.236: I/test_01(17747): B getActivity()=com.scanillion.demo.VerboseActivity@43ba3360
02-23 21:25:48.439: I/TestRunner(17747): finished: test_01(com.scanillion.demo.test.VerboseTest)
02-23 21:25:48.439: I/TestRunner(17747): passed: test_01(com.scanillion.demo.test.VerboseTest)

Note that finish() caused onDestroy(), but the subsequent getActivity() was a no-op. Not only does getActivity() not instantiate a new Activity, it doesn't even recreate the original one.

like image 38
cdhabecker Avatar answered Dec 08 '22 10:12

cdhabecker