你怎么测试在多个活动Android应用程序?多个、你怎么、应用程序、测试

2023-09-12 06:51:34 作者:小嘴嘟嘟o( ̄3 ̄)o

我们正在构建一个复杂的Andr​​oid应用程序,包括许多屏幕,并在许多活动的工作流程小号$ P $垫。我们的工作流程是类似于您可能一银行的ATM机上看到的,例如,有一个活动登录在过渡到主菜单活性这可以过渡到根据用户的选择的其他活动。

We are building a complex Android application consisting of many screens and workflows spread across many Activities. Our workflows are similar to what you might see on a Bank's ATM machine, for example, there is an Activity to login in that transitions to a main menu Activity which can transition to other activities based on the user's choices.

由于我们,所以我们需要创建一个跨越多个活动,让我们可以从端到端测试工作流程自动化的测试很多的工作流程。例如,使用ATM的例子,我们将要进入​​一个有效的识别码,确认派遣我们到主菜单,选择提取现金,确认我们是提取现金屏幕上,等等,等等,并最终发现自己回到主菜单或登陆上了。

Since we have so many workflows we need to create automated tests that span multiple activities so we can test a workflow from end to end. For example, using the ATM example, we would want to enter a valid PIN, verify that sends us to the main menu, choose withdraw cash, verify that we are on the withdraw cash screen, etc., etc., and eventually find ourselves back on the main menu or "logged" out.

我们已经把玩测试的API,来与Android(如 ActivityInstrumentationTestCase2 ),并与的正电子,但也似乎能够超越单个活动的边界测试,虽然我们可以找到一些工具这些工具对于一些单元测试,它们将无法满足我们的需求,用于测试场景,在多个活动切割。

We've toyed with the test APIs that come with Android (e.g. ActivityInstrumentationTestCase2) and also with Positron, but neither seem capable of testing beyond the bounds of a single Activity, and while we can find some utility in these tools for some unit testing, they won't meet our needs for testing scenarios that cut across multiple Activities.

我们是开放的一个的xUnit框架,脚本,GUI记录/回放等,并且将AP preciate任何意见。

We are open to an xUnit framework, scripting, GUI recorders/playbacks, etc. and would appreciate any advice.

推荐答案

我觉得有点别扭约回答我的奖金问题,但在这里它是...

I feel a bit awkward about answering my own bounty question, but here it is...

我已经搜查高和低就这个问题和不能相信没有发表任何地方的答案。我已经非常接近。我可以肯定地运行,现在跨越活动测试,但我的实现似乎有一些时间的问题,其中的测试并不总是可靠地传递。这是我所知道的是跨多个活动,成功测试的唯一例子。希望我的提取和它的匿名没有引入错误。这是我输入用户名和密码登录活动,然后观察一个适当的欢迎消息一个简单的测试显示在不同的欢迎光临的活动:

I've searched high and low on this and can't believe there is no answer published anywhere. I have come very close. I can definitely run tests that span activities now, but my implementation seems to have some timing issues where the tests don't always pass reliably. This is the only example that I know of that tests across multiple activities successfully. Hopefully my extraction and anonymizing of it did not introduce errors. This is a simplistic test where I type a username and password into a login activity, and then observe a proper welcome message is shown on a different "welcome" activity:

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!"));
   }
}

这code显然不是很可读。其实我也提取它与英国类似的API一个简单的库,所以我只能说事情是这样的:

This code is obviously not very readable. I have actually extracted it into a simple library with an English-like API so I can just say things like this:

type("myUsername").intoThe(username_field);
click(login_button);

我已经测试了大约4活动的深度和感到满意的是该方法的工作原理,虽然正如我所说,那里似乎是一个偶然的时机问题,我还没有完全想通了。我仍然有兴趣在整个活动测试的任何其他方式审理。

I've tested to a depth of about 4 activities and am satisfied that the approach works though as I said, there appears to be an occasional timing issue I have not completely figured out. I am still interested in hearing of any other ways of testing across activities.