Android UI 由于 Robotium 无法找到 ImageButton 对象,测试有时会失败
Android UI tests occasionally fail due to Robotium being unable to find ImageButton objects
我正在尝试调试一个 Android UI 测试,该测试大约有 3% 的时间失败。
我们的测试 class 是这样开始的:
@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框架升级到最新版本,但并没有解决问题。
有人知道我们做错了什么吗?
我相信我已经找到原因了。据我所知,问题是由于 tearDown()
中的竞争条件造成的。根据 Robotium 源代码,finishOpenedActivities()
通过发送三次后退按钮来工作。但是,这似乎是在单独的线程上完成的。因此,即使新的测试用例开始,命令也可能会继续发送,导致正在测试的应用程序从视图中消失,并导致 Robotium 无法读取 UI.
考虑到应用程序已经在每次测试结束时被杀死,finishOpenedActivities()
似乎有点多余。我把那行注释掉后就没有再出现这个问题
我正在尝试调试一个 Android UI 测试,该测试大约有 3% 的时间失败。
我们的测试 class 是这样开始的:
@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框架升级到最新版本,但并没有解决问题。
有人知道我们做错了什么吗?
我相信我已经找到原因了。据我所知,问题是由于 tearDown()
中的竞争条件造成的。根据 Robotium 源代码,finishOpenedActivities()
通过发送三次后退按钮来工作。但是,这似乎是在单独的线程上完成的。因此,即使新的测试用例开始,命令也可能会继续发送,导致正在测试的应用程序从视图中消失,并导致 Robotium 无法读取 UI.
考虑到应用程序已经在每次测试结束时被杀死,finishOpenedActivities()
似乎有点多余。我把那行注释掉后就没有再出现这个问题