Тестване на кликване върху Android ListView с ActivityUnitTestCase

Приложих ListView, който стартира нов Activity, когато се щракне върху елемент от списък. Когато го тествам ръчно, работи перфектно. Но когато се опитам да направя автоматизиран тест с ActivityUnitTestCase, получавам NullPointerException, сякаш ListView е празно.

Основна дейност (частична):

public class MainActivity extends ListActivity {

  @Override
  protected void onResume() {
    super.onResume();

    String[] items = new String[] {"item 1", "item 2"};
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
    setListAdapter(adapter);

    getListView().setOnItemClickListener(new OnItemClickListener () {

      @Override
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        TextView clickedItem = (TextView) view;
        CharSequence clickedItemText = clickedItem.getText(); // throws a NullPointerException when running testWithPerformItemClick()!
        Intent intent = new Intent(MainActivity.this, ItemDisplayActivity.class);
        intent.putExtra("parameter", clickedItemText);
        startActivity(intent);
      }
    });
  }
}

Тестовият код, който е неуспешен:

public class MainActivityTest extends ActivityUnitTestCase<MainActivity> {

  ListView listView;
  View child0;

  public MainActivityTest() {
    super(MainActivity.class);
  }

  private void setUpTest() {
    MainActivity activity = startActivity(new Intent(), null, null);
    getInstrumentation().callActivityOnStart(activity);
    getInstrumentation().callActivityOnResume(activity);
    listView = (ListView) activity.findViewById(android.R.id.list);
    child0 = listView.getChildAt(0); // returns null!
  }

  public void testWithPerformClick() {
    setUpTest();

    child0.performClick(); // throws a NullPointerException!

    Intent startedIntent = getStartedActivityIntent();
    assertEquals("item 1", startedIntent.getStringExtra("parameter"));
  }

  public void testWithPerformItemClick() {
    setUpTest();
    long itemId = listView.getAdapter().getItemId(0);

    listView.performItemClick(child0, 0, itemId); // throws a NullPointerException!

    Intent startedIntent = getStartedActivityIntent();
    assertEquals("item 1", startedIntent.getStringExtra("parameter"));
  }

И двата тестови метода са неуспешни, защото listView.getChildAt(0) връща null. Защо ListView е празен? Как мога да го принудя да се актуализира с правилните деца?


person lacton    schedule 31.08.2013    source източник
comment
Опитвали ли сте performItemClick()?   -  person Ibungo    schedule 08.11.2013
comment
Използвайки performItemClick(), кодът отива малко по-далеч, до частта clickedItem.getText() на метода onItemClick. Веднъж там се повдига NPE, защото предоставеното view е null (тъй като getChildAt(0) връща null). Актуализиране на описанието на проблема, за да стане това по-ясно.   -  person lacton    schedule 09.11.2013


Отговори (2)


Според документацията, ако предпочитате функционален тест, трябва да използвате ActivityInstrumentationTestCase2 . За извършване на щракване работи по-добре. Отговорът @fewe е правилен, трябва да изчакате списъкът да бъде изчертан, за да изчакате фрагментът да бъде зареден, можете да използвате getInstrumentation().waitForIdleSync();

Опитайте нещо подобно.

public class ActivityTests extends
    ActivityInstrumentationTestCase2<Activity>

final ListView list = (ListView) mActivity.findViewById(R.id.listId);
         assertNotNull("The list was not loaded", list);
         getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {

                 list.performItemClick(list.getAdapter().getView(position, null, null),
                         position, list.getAdapter().getItemId(position));
             }

         });

 getInstrumentation().waitForIdleSync();

Тогава не можете да тествате, например, дали даден фрагмент е бил зареден.

  mFragment frag = mActivity.getFragment();
  assertNotNull("Fragment was not loaded", frag);
person dinhokz    schedule 27.05.2014

Това е така, защото списъкът все още не е изчертан. Трябва да изчакате да бъде начертан, преди да опитате да получите достъп до клетките му

person fewe    schedule 15.11.2013
comment
Това би имало смисъл. Но как да накарате програмата да изчака изготвянето на списъка? Какъв ред код трябва да се добави в метода setUpTest()? - person lacton; 16.11.2013
comment
Трябва да кажа, че търся най-добра практика и по този въпрос. Засега използвам повикване Thread.sleep. - person fewe; 17.11.2013