【发布时间】:2013-11-21 05:22:31
【问题描述】:
我正在开发一个带有单一活动的图形计算器应用程序。 (安卓 API 10) 布局相当复杂,40多个按钮占据了屏幕的下半部分 和一个框架布局作为屏幕的顶部。框架布局是一个子类 “ScreenFrame”包含计算器的“屏幕”。每个视图/视图组 在 ScreenFrame 中显示的是一个自定义视图/视图组,它显示计算 用户正在执行。想想 TI 图形计算器,可以看到整个表达式 带有操作符号...
我一直在编写 JUnit 测试,主要是继承 AndroidTestCase,因为我只需要 测试大部分代码的上下文,而不是整个活动框架。 但是,我已经到了想开始编写功能测试用例的地步 并且应用程序的某些部分需要整个活动框架才能运行。
所以这是让我完全难过的问题。 首先我将展示测试用例的代码
public class CommandTest extends ActivityInstrumentationTestCase2<Calculator> {
private Calculator _calculator;
public CommandTest(){
super(Calculator.class);
}
@Override
protected void setUp() throws Exception {
setActivityInitialTouchMode(true);
_calculator = getActivity();
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
_calculator.finish(); // doesn't make a difference if this line is there or not
}
public void testCircleBadSyntax1() {
_calculator.runOnUiThread(new Runnable() {
@Override public void run() {
Button twoButton = (Button) _calculator.findViewById(R.id.twoButton);
twoButton.performClick();
Button addButton = (Button) _calculator.findViewById(R.id.addButton);
addButton.performClick();
Button nineButton = (Button) _calculator.findViewById(R.id.nineButton);
nineButton.performClick();
Button enterButton = (Button) _calculator.findViewById(R.id.equalsButton);
enterButton.performClick();
}
});
Instrumentation inst = getInstrumentation();
inst.waitForIdleSync();
_calculator.runOnUiThread(new Runnable() {
@Override public void run() {
ScreenFrame screenFrame = (ScreenFrame) _calculator.findViewById(R.id.screenFrame);
assertNotNull(screenFrame);
AnswerSymbolGroup answer = screenFrame.getLastAnswer();
INumber number = answer.getNumberAnswer();
assertEquals(number.getValueInt(), 11);
}
});
_calculator.finish();
}
}
我刚刚向您展示了我是如何设置所有内容的以及上面的一个示例测试用例。所有测试用例都是相似的,测试的不是问题......主要问题是当我通过eclipse运行测试时,测试只是无限期地挂在第一个测试用例实例上,(我试着把它留而只是为了看看,它只是在第一个案例上用蓝色箭头坐在那里 45 分钟以上)。非常奇怪的是,当我按下模拟器上的 HOME 按钮或后退按钮时,测试用例就会运行。它给出了适当的响应。当按下按钮时,您看不到任何屏幕变化或其他应该看到的东西,但测试用例按应有的方式运行。意味着它通过或失败取决于我正在测试的代码。然后测试运行器会挂起下一个测试,直到我再次按下返回或主页按钮。
这不是一个可行的解决方案。我想在一个测试文件中有十到二十个案例(有时更多),我想让它们都成功运行,而不必在模拟器上按任何东西,特别是因为我有一个 Jenkins CI 设置,我用于我没有问题的所有其他测试。
所以我认为像 robotsium 这样的框架用于这些类型的测试会更适合处理这些类型的测试。
我在使用机器人时遇到了同样的问题。当我在模拟器上显示主屏幕的情况下运行机器人测试用例时,测试用例启动,打开计算器屏幕,然后无限期挂起。当我按下后退按钮,然后重新打开应用程序时,测试用例从头开始并继续按应有的方式工作,这意味着如果它正在测试的代码正确,则它通过,否则失败。但是,您确实可以看到机器人案例的适当变化。例如,如果给定的测试被调整为使用一个单独的变量来单击按钮并且没有 runOnUiThreads 的东西,那么在按下两个按钮后屏幕上会出现一个 2,然后在输入后会出现加号、9 和 11被按下。在下一个测试用例中,同样的事情发生了,它无限期地挂起。当我单击返回或主页,然后重新打开应用程序时,测试将继续进行。每个测试用例我都要重复这个过程。我还没有尝试在我的詹金斯单元中运行这些测试,(仍在研究如何无头运行机器人测试)。
我已经为此困惑了好几天了,我觉得我不应该再浪费时间去弄清楚它了。有没有其他人经历过这种行为。
我通常讨厌使用调试器来查找错误,因为我发现它比编写测试并将适当的输出记录到 LOGCAT 更耗时。但是,我尝试在这种情况下运行调试器以找出问题所在。 我知道测试用例挂在 getActivity() 行...我到达调试器中的点,我在主循环器中循环。 onCreate()、onStart() 和 onResume() 方法都完成了,整个屏幕都是可见的,但是一旦发生 它会一直挂起,直到我按下返回按钮或主页按钮。
我真的很想弄清楚为什么会发生这种情况并能够连续运行多个测试用例。
/** 在前两个答案出现后添加 **/ 对于第一个答案,我已经尝试将 activity.finish() 放在 tearDown() 方法中,没有区别......
对于第二个答案,我已经尝试了所有可能的枚举,即在测试 setUp 和 tearDown() 中放置 super.setUp() 和 super.tearDown() 的位置,但不将它们作为选项之一。
我尝试更彻底地运行调试器 getActivity() 方法,可以说代码卡在了 startActivitySync(Intent intent) 方法的 Instrumentation 类中。
在第 391 行运行 getTargetContext().startActivity(intent),然后它位于同步锁的下一部分...
getTargetContext().startActivity(intent);
do{
try{
mSync.wait();
} catch(InterruptedException e){
}
}while(mWaitingActivities.contains(aw));
return aw.activity;
【问题讨论】:
-
视图上无限重复的动画是否可能导致挂起而不是?
-
我遇到了同样的问题。你找到解决方案了吗?
标签: android unit-testing robotium