您好,我是Android Junit测试新手:
我在MainActivityFunctionalTest.java文件中编写了一些测试代码
MainActivityFunctionalTest.java:
package com.example.myfirstapp2.test;
public class MainActivityFunctionalTest extends ActivityInstrumentationTestCase2<Login>{
private static final String TAG = "MainActivityFunctionalTest";
private Login activity;
public MainActivityFunctionalTest() {
super(Login.class);
}
@Override
protected void setUp() throws Exception {
Log.d(TAG,"Set-Up");
super.setUp();
setActivityInitialTouchMode(false);
activity = getActivity();
}
public void testStartSecondActivity() throws Exception {
// add monitor to check for the second activity
ActivityMonitor monitor =
getInstrumentation().
addMonitor(DisplayMessageActivity.class.getName(), null, false);
//addMonitor(MainActivity.class.getName(), null, false);
// find button and click it
Button view = (Button) activity.findViewById(R.id.btnLogin);
// TouchUtils handles the sync with the main thread internally
TouchUtils.clickView(this, view);
// to click on a click, e.g., in a listview
// listView.getChildAt(0);
// wait 2 seconds for the start of the activity
DisplayMessageActivity startedActivity = (DisplayMessageActivity)
monitor
.waitForActivityWithTimeout(5000);
assertNotNull(startedActivity);
// search for the textView
TextView textView = (TextView) startedActivity.findViewById(R.id.Email);
// check that the TextView is on the screen
ViewAsserts.assertOnScreen(startedActivity.getWindow().getDecorView(),
textView);
// validate the text on the TextView
assertEquals("Text incorrect", "1http://www.vogella.com",
textView.getText().toString());
// press back and click again
this.sendKeys(KeyEvent.KEYCODE_BACK);
TouchUtils.clickView(this, view);
}
}
然而,我收到一个错误: java.lang.SecurityException:注入另一个应用程序需要INJECT_EVENTS权限
at com.example.myfirstapp2.test.MainActivityFunctionalTest.testStartSecondActivity(MainActivityFunctionalTest.java:70)
TouchUtils.clickView(this, view);
请帮忙
答案 0 :(得分:40)
我遇到了同样的问题,我的代码是这样的(对于正常的登录活动):
onView(withId(R.id.username))
.perform(new TypeTextAction("test_user"));
onView(withId(R.id.password))
.perform(new TypeTextAction("test123"));
onView(withId(R.id.login)).perform(click());
最后一行是使用SecurityException崩溃的。在最后一次输入文字后输出,键盘处于打开状态,因此在另一个应用程序中考虑了下一次点击。
要解决此问题,我只需在打字后关闭键盘即可。我还必须添加一些睡眠以确保键盘关闭,否则测试会不时地中断。所以最终的代码看起来像这样:
onView(withId(R.id.username))
.perform(new TypeTextAction("test_user"));
onView(withId(R.id.password))
.perform(new TypeTextAction("test123")).perform(closeSoftKeyboard());
Thread.sleep(250);
onView(withId(R.id.login)).perform(click());
这很好用。
答案 1 :(得分:27)
我遇到了同样的问题,并且添加了closeSoftKeyboard()方法为我解决了这个问题。
onView(withId(R.id.view)).perform(typeText(text_to_be_typed), closeSoftKeyboard());
答案 2 :(得分:7)
我自己也遇到了同样的问题,这就是我发现的关于这个问题的内容。
向您的应用添加INJECT_EVENTS权限,使Android Studio指出此类权限“仅授予系统应用”。此外,manifest.permissions的Google's reference guide表明此权限是“不供第三方应用程序使用。”
现在,您的应用程序可能不是系统应用程序。因此,添加此权限绝对不是一件好事,幸运的是不适用于您的第三方项目。至少在Android Studio上开发时。
我可以看到你在setUp方法中调用了 setActivityInitialTouchMode(false); 正如Google's best practices for UI testing所指出的那样,在测试用户界面时必须将触摸模式设置为<强>真即可。否则,您的测试夹具将无法与UI元素交互。
还有一件事。这是一个自动化测试,可模拟用户对您应用的操作。如果我们与设备交互(真实或虚拟,无关紧要),我们很可能会让其他事情获得焦点(即使在被测试的应用内),然后与setUp方法的触摸模式设置会发生冲突已经表演了。
最终,这就是发生在我身上的事情。我只是通过不点击/触摸/与正在运行测试的设备进行交互来解决我的问题。
答案 3 :(得分:7)
这是因为您的设备已锁定/任何其他打开的对话框已打开 /任何阻止测试能够点击按钮的东西。例如。如果手机被锁定 - 当测试试图点击按钮时,它不能,因为设备已被锁定。
我在模拟器上遇到了麻烦,因为它总是显示“启动器已经崩溃”。因此,无论何时尝试单击该按钮,都不能,因为警报对话框已打开。
简而言之,请确保您的屏幕已解锁且没有消息框干扰测试,并且可以点击按钮。
答案 4 :(得分:5)
对于有根设备,this file帮助了我很多。 它有:
Injector.pressBackButton();
Injector.pressHomeButton();
Injector.pressPowerButton();
Injector.showNotificationCenter();
Injector.swipeLeftRight();
Injector.swipeRightLeft();
Injector.touch(x, y);
答案 5 :(得分:2)
我的代码是使用replaceText而不是TypeText动作解决的:
onView(withId(R.id.username_edit_text)).perform(ViewActions.replaceText("user123"))
onView(withId(R.id.password_edit_text)).perform(ViewActions.replaceText("pass123"), closeSoftKeyboard())
答案 6 :(得分:1)
运行espresso测试时,我遇到了完全相同的问题和错误消息。其中一个在运行整个包时总是失败,但是当我独自运行它时它总是通过。有趣的是,问题发生了,因为我在AndroidManifest.xml中的一个活动中添加了以下行:
android:windowSoftInputMode="stateUnchanged|adjustResize"
删除或更改以上行后:
android:windowSoftInputMode="stateHidden"
提到测试在运行整个包时也正在通过。
答案 7 :(得分:0)
上下文:这可能是一个奇怪的利基问题,但我也遇到了这个失败,然后我意识到这是因为我有一个 Facebook Messenger 聊天头正好浮动在它试图点击的位置。
在关闭 FB Messenger 聊天头后,我的测试通过了。
并不是说这是适合所有人的 #1 解决方案,但绝对解决了我的问题。
答案 8 :(得分:0)
对我来说,我在 UI 测试中遇到了这个问题。我通过这样做在运行时将活动设置为全屏:
systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
我通过简单地再添加一个标志 View.SYSTEM_UI_FLAG_IMMERSIVE
解决了这个问题。
systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_IMMERSIVE
答案 9 :(得分:-2)
使用TouchUtils修复“注入其他应用程序需要INJECT_EVENTS权限”的更多方法......
EG。官方android开发者网站显示:
// Stop the activity - The onDestroy() method should save the state of the Spinner
mActivity.finish();
// Re-start the Activity - the onResume() method should restore the state of the Spinner
mActivity = getActivity();
然而,如果在测试方法中直接跟随TouchUtils.clickView,则会导致错误:
// Stop the activity - The onDestroy() method should save the state of the Spinner
mActivity.finish();
// Re-start the Activity - the onResume() method should restore the state of the Spinner
mActivity = getActivity();
// Possible inject error!
TouchUtils.clickView(this, someView);
然而,将其拆分为两个测试方法并允许setUp()在中间运行似乎可以解决问题(注意这是由方法名控制的,因为测试是按字母顺序运行的):
*调用一个intent后仍然可能会失败但是在调用完成后不再会这样做
public void testYTestFinishing() {
TouchUtils.clickView(this, someView);
// Finish & restart the activity
activity.finish();
}
// -------------------------------------------
// Called before every test case method
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(true);
activity = getActivity();
getViews();
}
// -------------------------------------------
public void testZOnReturn() {
TouchUtils.clickView(this, someView);
}
有趣的是,在TouchUtils之前放置setUp()中的内容可能会失败并且有效:
public void testYTestFinishing() {
TouchUtils.clickView(this, someView);
// Finish & restart the activity
activity.finish();
setActivityInitialTouchMode(true);
activity = getActivity();
getViews();
// SORRY, this fails here on some builds and succeeds on others
TouchUtils.clickView(this, someView);
}
您也可以在TouchUtils之前直接尝试waitForActivity超时,它可以在其他时间修复它,例如在调用intent之后:
*如果在同一测试方法中使用,仍会出现注入错误...需要拆分为另一种方法,如上所示。
Instrumentation.ActivityMonitor monitor = getInstrumentation()
.addMonitor(Instrumentation.ActivityMonitor.class.getName(),
null, false);
// Wait for activity to fix inject error; Increase or decrease as needed
monitor.waitForActivityWithTimeout(2000);
// Should no longer fail
TouchUtils.clickView(this, someView);
答案 10 :(得分:-2)
在同一活动中测试许多功能时,建议输入以下代码:
SystemClock.sleep(800);
在每个函数的开头。您可以对其进行自定义,但想法是要等待一定次数才能进行处理。