0

我有一个正在使用 Robotium 测试的类,在它的onPause()方法中我只是清除了EditText(我不需要在之后保留数据onPause())。

所以我有一个正在测试的课程:

@Override
protected void onPause() {
    super.onPause();
    mEdtPassword.setText("");
}

及测试方法:

public void testOnPauseOnStart() {
        Activity mActivity = getActivity();
        solo.typeText(0, CORRECT_PASSWORD);

        getInstrumentation().callActivityOnPause(mActivity);
    }

但后来我得到一个错误:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:854)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:4077)
at android.view.View.invalidate(View.java:10322)
at android.widget.TextView.invalidateRegion(TextView.java:4395)
at android.widget.TextView.invalidateCursor(TextView.java:4338)
at android.widget.TextView.spanChange(TextView.java:7186)
at android.widget.TextView$ChangeWatcher.onSpanAdded(TextView.java:8821)
at android.text.SpannableStringBuilder.sendSpanAdded(SpannableStringBuilder.java:979)
at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:688)
at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:588)
at android.text.Selection.setSelection(Selection.java:76)
at android.text.Selection.setSelection(Selection.java:87)
at android.text.method.ArrowKeyMovementMethod.initialize(ArrowKeyMovementMethod.java:302)
at android.widget.TextView.setText(TextView.java:3555)
at android.widget.TextView.setText(TextView.java:3425)
at android.widget.EditText.setText(EditText.java:80)
at android.widget.TextView.setText(TextView.java:3400)
at <package>.ui.CheckPasswordActivity.onPause(CheckPasswordActivity.java:182)

如果我使用solo.setActivityOrientation(Solo.LANDSCAPE)我不会收到此错误。

然后,如果我mEdtPassword.setText("")runOnUiThread()一切都很好。

所以问题是:

  1. 为什么我使用时没有这个例外,solo.setActivityOrientation()但我使用时却getInstrumentation().callActivityOnPause(mActivity)有,我认为两者都在做同样的事情。

  2. 我应该出于其他原因将类似的东西包裹mEdtPassword.setText("")onPause()其他地方,还是只是为了测试目的而需要它?runOnUiThread

  3. 这是否意味着如果我想对我的 UI 进行测试,我需要编写更多代码(比如在 UI 线程上运行普通操作)才能运行它们?

非常感谢您的澄清。

4

2 回答 2

0

所以这就是我所知道的这可能会帮助你:

1) 为什么我在使用solo.setActivityOrientation() 时没有这个异常,但是当我使用getInstrumentation().callActivityOnPause(mActivity) 时却有,我认为两者都在做同样的事情。

根据callActivityOnPause()的 javadoc

执行活动的 onPause() 方法的调用。默认实现只是调用该方法。

所以它会onPause()在不是 UI 线程的 on 线程上调用。现在,由于您正在设置值并在其中编辑文本,Activity onPause()因此会出错。因此,在您的EditText. 由于您没有在其中执行任何 UI 操作,setActivityOrientation()因此不会引发任何错误。

2) 我是否应该将诸如 mEdtPassword.setText("") 之类的东西包装在 onPause() 和 runOnUiThread 其他地方出于某些其他原因,或者我只是需要它用于测试目的?

3) 这是否意味着如果我想对我的 UI 进行测试,我需要编写更多代码(比如在 UI 线程上运行普通操作)才能运行它们?

我会一起回答第二点和第三点。您无需更改活动即可使其可测试。如果您现在正在测试的活动方法正在执行与 UI 相关的任务,那么您可以将UiThreadTest注释放到您的测试方法中。您还可以阅读此链接以获取更多信息。

我的知识仅来自阅读我自己没有测试过的 java 文档。所以请试一试,让我知道它是如何工作的..

于 2013-02-13T07:40:36.077 回答
0

Praful 基本上是正确的,尽管我相信您无法在使用 @UiThreadTest 注释的测试中使用检测方法。这意味着您最好的选择实际上是将检测方法包装在可以发布到主线程的可运行文件中。例如:

public void callActivityOnPause(final Activity activity){
    getInstrumentation().runOnMainSync(new Runnable() {
            public void run() {
                activity.onpause();
            }
        });
}

我没有尝试过这段代码,所以它可能是错误的,只是在火车上消磨时间!

于 2013-02-16T18:13:17.647 回答