3

In my app, clicking on a certain checkbox should enable a menu item on the action bar. This works correctly when I run the app manually. However, the automated JUnit/Robotium tests fail when checking for the menu item's view.

Why do I see different behavior in my test suite?

Here is the test code:

public class FilterCardsTest extends ActivityInstrumentationTestCase2<FragmentTestActivity> {

    public FilterCardsTest() {
        super(FragmentTestActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        this.activity = this.getActivity();
        this.activity.replaceFragment(new FilterCards());
        this.getInstrumentation().waitForIdleSync();
        this.solo = new Solo(this.getInstrumentation(), this.activity);
    }

    public void testBrandCheckBox() {
        this.testCheckBox(R.id.brand_check, R.id.brand_input);
    }

    private void testCheckBox(int checkId, int inputId) {
        CheckBox cb = (CheckBox) this.activity.findViewById(checkId);
        EditText input = (EditText) this.activity.findViewById(inputId);
        this.solo.clickOnView(cb);
        this.getInstrumentation().waitForIdleSync();
        Assert.assertTrue(input.isEnabled());
        Assert.assertTrue(input.hasFocus());

        Assert.assertTrue(this.solo.waitForView(R.id.save_menu)); // FilterCardsTest.java:106
    }
}

To test fragments, I created a stub FragmentTestActivity:

public class FragmentTestActivity extends FragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_activity);
    }

    public void replaceFragment(Fragment fragment) {
        this.getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.fragment_container, fragment)
                .commit();
    }

}

And the code to set the checkboxes onClickListener() as well as the code which enables the menu item:

@Override
public void onPrepareOptionsMenu(Menu menu) {
    MenuItem confirm = menu.findItem(R.id.save_menu);

    if (this.numberChecked() > 0) {
        confirm.setVisible(true);
        confirm.setEnabled(true);
    } else {
        confirm.setVisible(false);
        confirm.setEnabled(false);
    }
}

private View.OnClickListener onCheckBoxClick = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        EditText input = null;

        for (int i = 0; i < CHECKBOXES.length; i++) {
            if (v.getId() == CHECKBOXES[i]) {
                input = (EditText) FilterCards.this.getActivity().findViewById(TEXT_FIELDS[i]);
            }
        }

        FilterCards.this.toggleTextField(input);
        FilterCards.this.getActivity().supportInvalidateOptionsMenu();
    }
};

And the logcat:

junit.framework.AssertionFailedError
at bbct.android.common.activity.test.FilterCardsTest.testCheckBox(FilterCardsTest.java:106)
at bbct.android.common.activity.test.FilterCardsTest.testBrandCheckBox(FilterCardsTest.java:114)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1584)
Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • Can you add the exact error message? Is it an assertion failure? or getting the control fails? – Rob Jun 06 '14 at 01:27
  • @Rob Thanks for the reminder. I should know better. I also commented the line where the assertion failure occurs. – Code-Apprentice Jun 06 '14 at 01:33
  • So presumably, it's waiting 20s (default timeout) and the save menu is never appearing. You are watching this test run, no? Does the save never appear? The two prior asserts would make you think that there is no error in the code that is triggering the actions.. ? – Rob Jun 06 '14 at 01:47
  • During the test run, the save icon never appears. But when I run it manually, it does. – Code-Apprentice Jun 06 '14 at 02:13
  • 2
    @Rob One thought: The `onPrepareOptionsMenu()` is in a `Fragment`. To test, I have a `FragmentTestActivity` which loads the `Fragment` into a stub activity. This potentially could be the cause of the different behavior I see during tests vs. during manual execution of the app. – Code-Apprentice Jun 06 '14 at 02:18
  • I am really interested in this. I just got done doing a bunch of unit testing with Robotium. – Rob Jun 06 '14 at 02:45
  • @Rob Stepping through the test code with a debugger shows that the app is behaving as expected. In particular, `onPrepareOptionsMenu()` executes the if-branch that enables the save menu item. – Code-Apprentice Jun 06 '14 at 02:55

1 Answers1

1

The action bar item does not appear because FragmentTestActivity only extends FragmentActivity. It should rather extend ActionBarActivity.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268