所以我有这个包含3个元素的测试活动:TextView、EditText和Button。当用户单击按钮时,"活动"会将文本从EditText转换为TextView中的某些文本。
问题是:如何为此类活动编写单元测试?
我的问题是:我应该在一个线程中"点击"(.performClick)按钮,但在另一个线程异步等待,但这打破了单元测试的逻辑,因为它运行以"test"前缀开头的每个测试,如果没有不成功的断言,则将test标记为"Ok"。
单元测试代码:
public class ProjectToTestActivityTest extends ActivityInstrumentationTestCase2<ProjectToTestActivity> {
private TextView resultView;
private EditText editInput;
private Button sortButton;
public ProjectToTestActivityTest(String pkg, Class activityClass) {
super("com.projet.to.test", ProjectToTestActivity.class);
}
public void onTextChanged(String str)
{
Assert.assertTrue(str.equalsIgnoreCase("1234567890"));
}
@Override
protected void setUp() throws Exception {
super.setUp();
Activity activity = getActivity();
resultView = (TextView) activity.findViewById(R.id.result);
editInput = (EditText) activity.findViewById(R.id.editInput);
sortButton = (Button) activity.findViewById(R.id.sortButton);
resultView.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable arg0) {
onTextChanged(arg0.toString());
}
}
}
protected void testSequenceInputAndSorting()
{
editInput.setText("1234567890");
sortButton.performClick();
}
}
假设业务逻辑在应用程序项目下的"活动"中正确实现,换句话说,当单击按钮时,将文本从EditText复制到TextView。
如何为此类活动编写单元测试
public void testButtonClick() {
// TextView is supposed to be empty initially.
assertEquals("text should be empty", "", resultView.getText());
// simulate a button click, which copy text from EditText to TextView.
activity.runOnUiThread(new Runnable() {
public void run() {
sortButton.performClick();
}
});
// wait some seconds so that you can see the change on emulator/device.
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// TextView is supposed to be "foo" rather than empty now.
assertEquals("text should be foo", "foo", resultView.getText());
}
更新:
如果您在主应用程序代码中不使用线程,主应用程序中只有UI线程,所有UI事件(单击按钮、更新textView等)都在UI线程中连续处理,则这种连续的UI事件不太可能停滞/延迟超过几秒钟。如果您仍然不太确定,请使用waitForIdleSync()使测试应用程序等待,直到在主应用程序的UI线程上不再处理UI事件:
getInstrumentation().waitForIdleSync();
assertEquals("text should be foo", "foo", resultView.getText());
然而,getInstrumentation().waitForIdleSync();
不会等待在您的主应用程序代码中生成的线程,例如,当单击按钮时,它启动AsyncTask处理耗时的作业,并在完成后(比如在3秒内)更新TextView,在这种情况下,您必须使用Thread.sleep();
使您的测试应用程序停止并等待,请查看此链接中的答案以获取代码示例。