2016-09-14 10 views
1

Я пытаюсь отладить тест UI для Android, который не работает в 3% случаев.Тесты пользовательского интерфейса Android иногда из-за того, что Robotium не может найти объекты ImageButton

Наш тестовый класс начинается так:

@RunWith(AndroidJUnit4.class) 
public class ActionWidgetAdapterTest { 

    private Solo solo; 

    @Rule 
    public ActivityTestRule<SampleContainer> mActivityRule = new ActivityTestRule<>(SampleContainer.class); 

    // SampleContainer is used exclusively for the test case and extends AppCompatActivity 

    @Before 
    public void setUp() throws Exception { 
     solo = new Solo(InstrumentationRegistry.getInstrumentation(), mActivityRule.getActivity()); 
    } 

    @After 
    public void tearDown() throws Exception { 
     solo.finishOpenedActivities(); 
    } 
    // rest of class 
    // [...] 
} 

Проблематика тест выглядит следующим образом:

@Test 
@LargeTest 
@FlakyTest 
public void testAddActions() throws Exception { 

    final ArrayList<Action> actions = new ArrayList<>(); 

    // Action is our in-house version of the Action class from the Leanback library 
    final Action a1 = new Action(0, "text1", R.drawable.action_button_focused); 
    final Action a2 = new Action(1, "text2", R.drawable.action_button_focused); 
    final Action a3 = new Action(0, "text3", R.drawable.action_button_focused); 
    final Action a4 = new Action(1, "text4", R.drawable.action_button_focused); 

    actions.add(a1); 
    actions.add(a2); 
    actions.add(a3); 
    actions.add(a4); 

    // handler for posting to the main thread 
    Handler mainHandler = new Handler(mActivityRule.getActivity().getBaseContext() 
                   .getMainLooper()); 

    Runnable myRunnable =() -> { 

     // add actions to adapter 
     mActivityRule.getActivity().mActionWidgetAdapter.addActions(actions); 
    }; 
    mainHandler.post(myRunnable); 

    solo.sleep(1000); // pause to resolve any timing issues 
    assertTrue(mActivityRule.getActivity().mActionWidgetAdapter.getItemCount() == 4); 

    // test edge case - navigate all the way to the left 
    solo.sendKey(Solo.LEFT); 
    pressUpDownEnter(); 
    solo.sendKey(Solo.LEFT); 
    pressUpDownEnter(); 
    solo.sendKey(Solo.LEFT); 
    pressUpDownEnter(); 
    solo.sendKey(Solo.LEFT); 
    pressUpDownEnter(); 
    solo.sendKey(Solo.LEFT); 

    assertTrue(solo.getImageButton(0).isFocused()); 
    assertFalse(solo.getImageButton(2).isFocused()); 
} 

Тестовый пример проходит подавляющее большинство времени. Однако есть небольшая вероятность сбоя при выполнении assertTrue(solo.getImageButton(0).isFocused());; Robotium жалуется, что «3 ImageButtons не найдены», когда это происходит. Похоже, что нет такого шаблона. Я обновил структуру Robotium до последней версии, но это не решает проблему.

У кого-нибудь есть идея, что мы делаем неправильно?

ответ

1

Я считаю, что нашел причину. Из того, что я мог сказать, проблема связана с состоянием гонки в tearDown(). В исходном коде Robotium finishOpenedActivities() работает, отправив кнопку «Назад» трижды. Однако это, по-видимому, выполняется в отдельном потоке. В результате команды могут продолжать отправляться, даже когда начинается новый тестовый сценарий, в результате чего тестируемое приложение исчезает из представления и не позволяет Robotium не читать интерфейс.

Учитывая, что приложение уже убито в конце каждого теста, finishOpenedActivities() будет казаться излишним. Проблема не возникла после того, как я прокомментировал эту строку.