我有一个正在使用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()
,一切都很好。
所以问题是:
为什么我使用solo.setActivityOrientation()
时没有这个例外,但是当我使用getInstrumentation().callActivityOnPause(mActivity)
时我会这样做,我认为两者都在做同样的事情。
我是否应该将mEdtPassword.setText("")
中的onPause()
之类的内容与其他地方的runOnUiThread
包装在一起,或者我只是需要它用于测试目的?
这是否意味着如果我想要测试我的UI我需要编写更多代码(比如在UI线程上运行普通操作)以便可以运行它们?
非常感谢您的澄清。
答案 0 :(得分:0)
这就是我所知道的对你有用的东西:
的javadoc1)为什么我使用时没有此异常 solo.setActivityOrientation()但是当我使用时我会这样做 getInstrumentation()。callActivityOnPause(mActivity),我假设两者 正在做同样的事情。
执行调用活动的onPause()方法。默认 实现只是调用该方法。
所以它会在其线程上调用onPause()
而不是UI线程。现在,由于您要在Activity
onPause()
中设置值并编辑文本,因此会出错。因此,EditText
上设置值的错误原因。由于您没有在setActivityOrientation()
中执行任何UI操作,因此不会抛出任何错误。
2)我应该在onPause()中包含mEdtPassword.setText(“”)这样的内容 runOnUiThread在其他地方出于其他原因或我只是需要它 用于测试目的?
3)这是否意味着如果我想要我的UI测试我需要写更多 代码(比如在UI线程上运行普通操作)来实现它 可以运行它们吗?
我会一起回答第二点和第三点。您无需更改活动以使其可测试。如果您现在正在测试的活动方法正在执行与UI相关的任务,那么您可以将UiThreadTest注释添加到测试方法中。您还可以阅读此link了解更多信息..
我的知识只来自阅读我自己没有测试过的java文档。所以,请试一试,让我知道它是如何工作的。
答案 1 :(得分:0)
Praful大部分是正确的,但我相信你无法在使用@UiThreadTest注释的测试中使用乐器方法。这意味着你最好的选择实际上是在一个可以发布到主线程的runnable中包装instrumentation方法。例如:
public void callActivityOnPause(final Activity activity){
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
activity.onpause();
}
});
}
我没有尝试过这段代码,所以它可能是错的,只是在火车上消磨时间!