我们正在构建一个复杂的 Android 应用程序,该应用程序由分布在许多活动中的许多屏幕和工作流组成.我们的工作流程类似于您在银行的 ATM 机上看到的工作流程,例如,有一个 Activity
可以登录,转换到主菜单 Activity
可以转换到基于用户选择的其他活动.
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 示例,我们想输入一个有效的 PIN,验证将我们发送到主菜单,选择提取现金,验证我们是否在提取现金屏幕上等等,最终找到自己返回主菜单或退出".
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.
我们玩弄了 Android 附带的测试 API(例如 ActivityInstrumentationTestCase2
)以及 Positron,但似乎都无法测试超出单个 Activity
的范围,虽然我们可以在这些工具中找到一些实用程序来进行某些单元测试,但它们不会无法满足我们对跨越多个活动的测试场景的需求.
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 记录器/回放等持开放态度,并希望得到任何建议.
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!"));
}
}
这段代码显然不是很可读.我实际上已经将它提取到一个带有类似英语 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.
这篇关于如何跨多个活动测试 Android 应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!