在Robotium中按下一个或完成的键

时间:2012-11-27 23:41:03

标签: android functional-testing robotium

我只是想与Robotium试图通过功能测试重现错误。我的活动未设置为正确处理" next"在登录期间从用户名字段移动到密码字段时的密钥。我谷歌搜索了一下,我无法解决问题。我在Galaxy Nexus上试过这个:

    solo.clearEditText(0);
    solo.enterText(0, Constants.TEST_ACCOUNT_1.getUsername());
    solo.clickOnEditText(0);
    solo.clickOnScreen(672,1132);
    solo.clickOnEditText(0);
    solo.sleep(15000);
    solo.enterText(1, Constants.TEST_ACCOUNT_1.getPassword());

想法是单击文本字段以抬起键盘,然后尝试单击下一个按钮,但编辑文本字段中的单击不会抬起键盘。我也试过发送回车键,我尝试使用FLAG_EDITOR_ACTION发送回车键,它们都没有模拟"下一步"键。救命啊!

2 个答案:

答案 0 :(得分:6)

Robotium似乎没有显示键盘的方法。此外,似乎键盘在Robotium可以与之交互的范围之外运行,因为clickOnText()即使可见,也不会按下软键盘按钮。因此,这个答案将会是一个黑客攻击。

解决方案有两个重要部分。首先,虽然我们无法使用dispatchKeyEvent直接单击IME Next按钮,但我们可以使用其他键盘按钮,我们可以使用EditText.onEditorAction(EditorInfo.IME_ACTION_NEXT)触发其回调。这将允许我们跳到下一个EditText。其次,触发此回调属于“与UI交互”的类别,因此我们必须从运行Robotium的线程转回主线程以进行调用。我们将使用Activity.runOnUiThread()来实现此目标。

这是一个如何为我工作的例子:

public void testImeNext() throws Exception
{
    //Grab a reference to your EditText.  This code grabs the first Edit Text in the Activity
    //Alternatively, you can get the EditText by resource id or using a method like getCurrentEditTexts()
    //Make sure it's final, we'll need it in a nested block of code.
    final EditText editText = solo.getEditText(0);

    //Create a runnable which triggers the onEditorAction callback
    Runnable runnable = new Runnable() 
    {
        @Override
        public void run() 
        {
            editText.onEditorAction(EditorInfo.IME_ACTION_NEXT);
        }
    };

    //Use Solo to get the current activity, and pass our runnable to the UI thread.
    solo.getCurrentActivity().runOnUiThread(runnable);
}

答案 1 :(得分:4)

在另一个答案的基础上,我编写了一个模拟IME按钮按下的方法,直到UI线程上的请求完成后才返回。

/**
 * This will send the NEXT action to simulate pressing next on the keyboard.
 * Because it has to be run on the UI thread we use a barrier to block and
 * stop this request returning until the action is complete.
 **/
private void sendIMENext(final EditText editText) throws Exception {
    final CyclicBarrier barrier = new CyclicBarrier(2);

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            editText.onEditorAction(EditorInfo.IME_ACTION_NEXT);

            try {
                barrier.await();
            }
            catch (Exception e) {
                Log.e("MainActivityTest", "Interupted on UI thread pressing IME next", e);
            }
        }
    };

    //Use Solo to get the current activity, and pass our runnable to the UI thread.
    solo.getCurrentActivity().runOnUiThread(runnable);
    // Waits until the barrier is met in the runnable
    barrier.await();
}

这应该总是返回,但如果你愿意,可以在第二个 await 中添加超时。