4

I am fairly new to testing and am trying to explore jUnit Tests and Robotium. My application has 4 screens.

Splash Screen --> Screen2--> Screen 3--> Autocomplete Screen.
[init()]                               [ check values generated by init() method]

Autocomplete screen is where the user types something, and the app performs autocomplete from a large database of Products. In the splash screen I am initializing many app variables using an init() method in another class. This init() method will load usedr preferences, check for database creation etc...(The product database comes pre-packaged in the apk and i am copying the database on first launch and mark it in SharedPreferences as copied=true).

Problem : How do i isolate the testing of Autocomplete Screen ? The onCreate of AutocompleteActivity depends on init() having been called in the SplashScreen. I am not sure when the jUnit creates an instance of the Activity, (probably in the constructor? ). Here is my TestCaseCode:

import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.widget.ListView;

import com.jayway.android.robotium.solo.Solo;
import com.supervalu.mobile.android.AutoCompleteActivity;
import com.supervalu.mobile.android.db.LocalDb;

public class AutocompleteTest extends
        ActivityInstrumentationTestCase2<AutoCompleteActivity> {
private Solo solo;

public AutocompleteTest() {
    super("com.****.*****.*****", AutoCompleteActivity.class);
}

protected void setUp() throws Exception {
    super.setUp();
    LocalDb.init(getActivity().getApplicationContext());
    solo = new Solo(getInstrumentation(), getActivity());

}

public void test1Character() {
    solo.sleep(2000);
    solo.enterText(0, "c");
    solo.sleep(10000);
View v = getActivity().findViewById(
            com.*****.****.*****.R.id.list);
    solo.waitForView(v);
    assertTrue(((ListView) v).getChildCount() > 0);


}

public void test3Character() {
    LocalDb.init(getActivity().getApplicationContext());
    solo.enterText(0, "che");
    View v = getActivity().findViewById(
            com.*****.****.*****.R.id.list);
    solo.waitForView(v);
    assertTrue(((ListView) v).getChildCount() > 0);
}

protected void tearDown() throws Exception {

    solo.finishOpenedActivities();
    super.tearDown();

}

The test case keeps creashing because the onCreate requires some values from the LocalDb whcih had to be initialiazed by init() method.

I cannot add the init() function before the super call in the constructor. Is there any work around for this , or do i need to start the test case from the splash screen ?

Problem 2 : If i start testing from splash scree, I have to first navigate to the autocmplete screen before being able to perform any tests on it. Suppose i did that as well, then for each test: test1character() the class executes setUp() and then the test and then tearDown(), then it restarts whole sequence for test3characters() function. It gets very painful to keep repeating navigating to autocompltete screen every time before actually testing inputs. Any suggestions on this as well ?

I am not sure what approach to take. Can someone please guide me?

rDroid
  • 4,875
  • 3
  • 25
  • 30

4 Answers4

3

I had a similar problem and was able to fix it. In your setUp() method it is no use to call getActivity(). It doesn't affect your test methods. You have to use:

getInstrumentation().getTargetContext()

for example use

getInstrumentation().getTargetContext().getContentResolver()

instead of

getActivity().getContentResolver()

Hope this works for you!

Cheers Antonino

0

If your doing unit testing , You should extend your test class to ActivityUnitTestCase to test a single activity and use startActivity method which will call your onCreate. ActivityInstrumentationTestCase2 is for functional testing the activity.

see more from the android reference doc...

Start the activity under test, in the same way as if it was started by Context.startActivity(), providing the arguments it supplied. When you use this method to start the activity, it will automatically be stopped by tearDown().

This method will call onCreate(), but if you wish to further exercise Activity life cycle methods, you must call them yourself from your test case.

Do not call from your setUp() method. You must call this method from each of your test methods.

Libin
  • 16,967
  • 7
  • 61
  • 83
0

I found mocking frameworks to be better alternative to perform isolated method tests of android activities methods. At the moment jMockit is only framework capable to mock up endroid base classes effectively.

You will be able to discard a lot of setup and teardown code. See test case:

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

Konstantin Pribluda
  • 12,329
  • 1
  • 30
  • 35
0

I'm not really understand your problem, but I will try to help.

To perform the Activity start (and calls to the onCreate callback of it) is with:

getActivity();

A usual place for it is in the setUp() method (to call before each test).

As you say for each test the setUp() and tearDown() methods are called.

I think that the best way to test your app navigation is in a simple test, and create all intents as you need to can start all the Activities nedded to test.

I hope it helps.

sabadow
  • 5,095
  • 3
  • 34
  • 51