如何在多个活动中测试Android应用程序?

Sin*_*hot 79 android integration-testing automated-tests android-testing

我们正在构建一个复杂的Android应用程序,其中包含许多活动中的许多屏幕和工作流程.我们的工作流程类似于您在银行的ATM机上看到的工作流程,例如,有一个Activity登录过渡到主菜单Activity,可以根据用户的选择转换到其他活动.

由于我们有如此多的工作流程,因此我们需要创建跨多个活动的自动化测试,以便我们可以从头到尾测试工作流程.例如,使用ATM示例,我们希望输入有效的PIN码,验证是否将我们发送到主菜单,选择提取现金,验证我们是否在提取现金屏幕等等,并最终找到自己回到主菜单或"登出".

我们玩过Android(例如ActivityInstrumentationTestCase2)和Positron附带的测试API ,但似乎都没有超出单一范围的测试能力Activity,虽然我们可以在这些工具中找到一些用于某些单元测试的实用工具,但他们赢了不能满足我们测试多个活动的测试场景的需求.

我们对xUnit框架,脚本,GUI记录器/回放等持开放态度,并对任何建议表示感谢.

Sin*_*hot 65

回答我自己的赏金问题我觉得有点尴尬,但这里是......

我对此进行了高调和低调,并且无法相信在任何地方都没有发布任何答案.我已经非常接近了.我现在肯定可以运行跨越活动的测试,但我的实现似乎有一些时间问题,其中测试并不总是可靠地通过.这是我所知道的成功跨多个活动的唯一示例.希望我的提取和匿名化不会引入错误.这是一个简单的测试,我在登录活动中键入用户名和密码,然后在不同的"欢迎"活动中显示正确的欢迎消息:

package com.mycompany;

import android.app.*;
import android.content.*;
import android.test.*;
import android.test.suitebuilder.annotation.*;
import android.util.*;
import android.view.*;
import android.widget.*;

import static org.hamcrest.core.Is.*;
import static org.hamcrest.core.IsNull.*;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.*;
import static com.mycompany.R.id.*;

public class LoginTests extends InstrumentationTestCase {

   @MediumTest
   public void testAValidUserCanLogIn() {

      Instrumentation instrumentation = getInstrumentation();

      // Register we are interested in the authentication activiry...
      Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(AuthenticateActivity.class.getName(), null, false);

      // Start the authentication activity as the first activity...
      Intent intent = new Intent(Intent.ACTION_MAIN);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      intent.setClassName(instrumentation.getTargetContext(), AuthenticateActivity.class.getName());
      instrumentation.startActivitySync(intent);

      // Wait for it to start...
      Activity currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5);
      assertThat(currentActivity, is(notNullValue()));

      // Type into the username field...
      View currentView = currentActivity.findViewById(username_field);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(EditText.class));
      TouchUtils.clickView(this, currentView);
      instrumentation.sendStringSync("MyUsername");

      // Type into the password field...
      currentView = currentActivity.findViewById(password_field);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(EditText.class));
      TouchUtils.clickView(this, currentView);
      instrumentation.sendStringSync("MyPassword");

      // Register we are interested in the welcome activity...
      // this has to be done before we do something that will send us to that
      // activity...
      instrumentation.removeMonitor(monitor);
      monitor = instrumentation.addMonitor(WelcomeActivity.class.getName(), null, false);

      // Click the login button...
      currentView = currentActivity.findViewById(login_button;
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(Button.class));
      TouchUtils.clickView(this, currentView);

      // Wait for the welcome page to start...
      currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5);
      assertThat(currentActivity, is(notNullValue()));

      // Make sure we are logged in...
      currentView = currentActivity.findViewById(welcome_message);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(TextView.class));
      assertThat(((TextView)currentView).getText().toString(), is("Welcome, MyUsername!"));
   }
}
Run Code Online (Sandbox Code Playgroud)

这段代码显然不是很易读.我实际上把它提取到一个带有类似英语的API的简单库中,所以我可以这样说:

type("myUsername").intoThe(username_field);
click(login_button);
Run Code Online (Sandbox Code Playgroud)

我已经测试了大约4个活动的深度,并且我很满意这种方法虽然如我所说,但似乎偶尔出现时间问题,我还没有完全弄明白.我仍然有兴趣听到跨活动测试的任何其他方式.

  • 您可以尝试添加FlakyTest注释,以便在计时问题导致其失败时自动重复测试.实际上,这不是解决方案,而是在某些情况下可行的解决方法. (3认同)

Jon*_*röm 22

看看Robotium
是一个开源测试框架,它创建的Android应用程序的自动黑盒测试比开箱即用的Android仪器测试更快更容易.

主页: http
://www.robotium.org/来源:http: //github.com/jayway/robotium

请注意,Robotium项目由我工作的公司维护

  • Robotium是一个救生员.这将使你的测试非常容易编写(你基本上用简单的英语与它交谈:点击它,按回按钮等)你可以测试任何东西,但你不需要知道微小的细节.它至少有两个主要的好处:你可以测试你没有源代码的应用程序,它依赖于UI,使其非常强大(你更改控制器/模型比你的视图更多......) (2认同)

Ren*_*nas 8

你总是可以使用Robotium.它支持黑盒测试,就像Selenium一样,但支持Android.你会在Robotium.org找到它

  • 只要它们属于同一个进程,它就一直在各个活动中工作. (3认同)