【问题标题】:ActivityInstrumentationTestCase2 AND Robotium test cases hang until back/home pressed on emulator, WHY?ActivityInstrumentationTestCase2 和 Robotium 测试用例挂起,直到在模拟器上按下返回/主页,为什么?
【发布时间】: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


【解决方案1】:

在你的tearDown方法中,你需要调用_calculator.finish();

对于打开多个活动的测试,robotium 有一个方便的方法来完成所有活动:solo.finishOpenedActivities();

【讨论】:

  • 我没有在我发布的代码中显示,但我确实在 tearDown() 方法中调用了这些方法,并且我的应用程序中只有一个活动......跨度>
【解决方案2】:

我不确定它是否对您有帮助,但是您应该在 setUp 方法的开头调用 super.setUp();,在 tearDown 方法的末尾调用 super.tearDown();。您也可以尝试删除它们。

顺便说一句,调用setActivityInitialTouchMode(false); 没有意义,因为:

如果你不调用它,触摸模式将是假的。如果你打电话 这在您的 Activity 启动后,将不起作用。

【讨论】:

    【解决方案3】:

    我遇到了类似的问题。我可以通过将setAdapter() 方法放在AsyncTask 类中来解决我的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-16
      • 2020-10-22
      • 2021-05-14
      • 2019-08-16
      • 1970-01-01
      • 1970-01-01
      • 2020-06-19
      相关资源
      最近更新 更多