如何在MaterialDialog中访问editText并执行键入(Android ui测试)
这是我的密码如何在MaterialDialog中访问editText并执行键入(Android ui测试),android,android-testing,android-espresso,Android,Android Testing,Android Espresso,这是我的密码 @RunWith(AndroidJUnit4.class) @LargeTest public class ChangeTextBehaviorTest { public static final String STRING_TO_BE_TYPED = "Espresso"; @Rule public ActivityTestRule<LandingActivity> mActivityRule = new ActivityTestRule<> (
@RunWith(AndroidJUnit4.class)
@LargeTest
public class ChangeTextBehaviorTest {
public static final String STRING_TO_BE_TYPED = "Espresso";
@Rule
public ActivityTestRule<LandingActivity> mActivityRule = new ActivityTestRule<> (
LandingActivity.class );
@Test
public
void changeText_sameActivity () {
String testText = "testText";
onView ( withId ( R.id.action_a) )
.perform ( click (), closeSoftKeyboard () );
onView ( withHint ( R.string.add_list ) ).perform ( typeTextIntoFocusedView ( testText ) );
onView ( withText ("ADD" ) ).perform ( click () );
}
但是测试出错了。该对话框似乎不在视图层次结构中
Running tests
Test running started
android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with string from resource id: <2131099668>[add_list] value: Add List
If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:com.nhaarman.listviewanimations.itemmanipulation.DynamicListView{42ed6100 V.ED.VCL ........ 0,0-1080,1692 #7f0c0074 app:id/listViewTaskInComplete}
View Hierarchy:
+>DecorView{id=-1, visibility=VISIBLE, width=1080, height=1920, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+->LinearLayout{id=-1, visibility=VISIBLE, width=1080, height=1920, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+-->ViewStub{id=16909084, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+-->FrameLayout{id=-1, visibility=VISIBLE, width=1080, height=1860, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=60.0, child-count=1}
|
+--->FitWindowsLinearLayout{id=2131492948, res-name=action_bar_root, visibility=VISIBLE, width=1080, height=1860, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+---->ViewStubCompat{id=2131492949, res-name=action_mode_bar_stub, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+---->ContentFrameLayout{id=16908290, res-name=content, visibility=VISIBLE, width=1080, height=1860, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+----->CoordinatorLayout{id=2131492976, res-name=rootLayout, visibility=VISIBLE, width=1080, height=1860, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3}
|
+------>AppBarLayout{id=-1, visibility=VISIBLE, width=1080, height=540, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+------->CollapsingToolbarLayout{id=2131492977, res-name=collapsingToolbarLayout, visibility=VISIBLE, width=1080, height=540, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+-------->ImageView{id=-1, visibility=VISIBLE, width=1080, height=540, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+-------->Toolbar{id=2131492978, res-name=toolbar, visibility=VISIBLE, width=1080, height=168, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+--------->View{id=-1, visibility=VISIBLE, width=888, height=168, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=48.0, y=0.0}
|
+--------->ActionMenuView{id=-1, visibility=VISIBLE, width=144, height=168, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=936.0, y=0.0, child-count=1}
|
+---------->ActionMenuItemView{id=2131493079, res-name=menu_setting, desc=Settings, visibility=VISIBLE, width=144, height=144, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=12.0, text=, input-type=0, ime-target=false, has-links=false}
|
+------>NestedScrollView{id=2131492979, res-name=nested_scroll_view, visibility=VISIBLE, width=1080, height=1860, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=540.0, child-count=1}
|
+------->DynamicListView{id=2131492980, res-name=listViewTaskInComplete, visibility=VISIBLE, width=1080, height=1692, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=0}
|
+------>FloatingActionsMenu{id=2131493035, res-name=multiple_actions, visibility=VISIBLE, width=222, height=828, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=429.0, y=1032.0, child-count=3}
|
+------->FloatingActionButton{id=2131493036, res-name=action_b, visibility=VISIBLE, width=222, height=222, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=138.0}
|
+------->FloatingActionButton{id=2131493037, res-name=action_a, visibility=VISIBLE, width=222, height=222, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=372.0}
|
+------->{id=2131492868, res-name=fab_expand_menu_button, visibility=VISIBLE, width=222, height=222, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=606.0}
|
我能想到两个可能的原因:
1可能是对话框仍在过渡,意大利浓咖啡不认为它是完全可见的。或者它尚未连接
有时浓缩咖啡会以这种方式失败——即使它承诺要等到主线程空闲时再运行,但有时却无法运行 当我需要在对话框上执行操作时,我使用两个helper方法等待一点转换和其他什么来完成。(代码如下) 2) Espresso正在错误的根视图上搜索视图单击“在材质对话框中查看”(使用与您相同的库) 等待转换完成
public void test() {
// Open another screen
goTo(new XyzScreen(DateTime.now(), null));
// Wait some time for transitions to complete
onView(isRoot()).perform(waitAtLeast(300));
// Now we can get a screenshot
screenshot(d);
}
/**
* Perform action of waiting for a specific time. Useful when you need
* to wait for animations to end and Espresso fails at waiting.
* <p/>
* E.g.:
* onView(isRoot()).perform(waitAtLeast(Sampling.SECONDS_15));
*
* @param millis
* @return
*/
public static ViewAction waitAtLeast(final long millis) {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return anything();
}
@Override
public String getDescription() {
return "wait for at least " + millis + " millis.";
}
@Override
public void perform(final UiController uiController, final View view) {
uiController.loopMainThreadUntilIdle();
uiController.loopMainThreadForAtLeast(millis);
}
};
}
/**
* Perform action of waiting until UI thread is free.
* <p/>
* E.g.:
* onView(isRoot()).perform(waitUntilIdle());
*
* @return
*/
public static ViewAction waitUntilIdle() {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return anything();
}
@Override
public String getDescription() {
return "wait until UI thread is free";
}
@Override
public void perform(final UiController uiController, final View view) {
uiController.loopMainThreadUntilIdle();
}
};
}
公共无效测试(){
//打开另一个屏幕
goTo(新的XyzScreen(DateTime.now(),null));
//等待一段时间以完成过渡
onView(isRoot()).perform(至少等待(300));
//现在我们可以截图了
截图(d);
}
/**
*执行等待特定时间的操作。当你需要的时候很有用
*等待动画结束,浓缩咖啡无法等待。
*
*例如:
*onView(isRoot()).perform(wait至少(Sampling.SECONDS_15));
*
*@param-millis
*@返回
*/
公共静态ViewAction至少等待(最终长毫秒){
返回新的ViewAction(){
@凌驾
公共匹配器getConstraints(){
返回任何内容();
}
@凌驾
公共字符串getDescription(){
返回“等待至少”+millis+“millis.”;
}
@凌驾
公共作废执行(最终UiController UiController,最终视图){
uiController.loopMainThreadUntilIdle();
uiController.loopMainThreadForAtLeast(毫秒);
}
};
}
/**
*执行等待UI线程空闲的操作。
*
*例如:
*onView(isRoot()).perform(waitUntilIdle());
*
*@返回
*/
公共静态ViewAction waitUntilIdle(){
返回新的ViewAction(){
@凌驾
公共匹配器getConstraints(){
返回任何内容();
}
@凌驾
公共字符串getDescription(){
返回“等待UI线程空闲”;
}
@凌驾
公共作废执行(最终UiController UiController,最终视图){
uiController.loopMainThreadUntilIdle();
}
};
}
我收到一个错误“return anything();”public static ViewAction waitUntilIdle(){return new ViewAction(){aooverride public Matcher getConstraints(){return anything();}aooverride public String getDescription(){return“等待UI线程空闲”}A跳过公共无效执行(最终UiController UiController,最终视图){UiController.loopMainThreadUntilIdle();};};}错误:(122,19)错误:需要不兼容的类型:Matcher发现:MatcherOh,这很奇怪,可能自从我编写代码以来smth发生了更改。它们使用此选项而不是anything()
Matcher:`public static Matcher anyView(){return new TypeSafeMatcher(){@Override public boolean matchessesafely(视图视图){return true;}@Override public void descripito(Description Description){};}`这篇文章修复了我的问题
public static
void showAddListDialog ( final Activity thisContext, final ListView listView ) {
MaterialDialog scoreDialog = new MaterialDialog.Builder ( thisContext )
//.customView ( R.layout.dialog_todo, true )
.title ( thisContext.getString ( R.string.add_list ) )
.positiveText ( "ADD" )
.input ( thisContext.getString ( R.string.add_list ), "", new MaterialDialog.InputCallback () {
@Override public
void onInput ( MaterialDialog materialDialog, CharSequence charSequence ) {
QueryHelper.addListToDB ( thisContext, String.valueOf ( charSequence ), listView );
}
} )
.negativeText ( "CANCEL" )
.show ();
}
public void test() {
// This opens time picker dialog
onView(withId(R.id.block_edit_start_time)).perform(click());
// Click on dialog OK button
performMaterialDialogOkClick();
}
/**
* Clicks positive button in visible/active {@link com.afollestad.materialdialogs.MaterialDialog}
*/
public static void performMaterialDialogOkClick() {
onView(withId(R.id.buttonDefaultPositive)).inRoot(isDialog()).perform(click());
}
public void test() {
// Open another screen
goTo(new XyzScreen(DateTime.now(), null));
// Wait some time for transitions to complete
onView(isRoot()).perform(waitAtLeast(300));
// Now we can get a screenshot
screenshot(d);
}
/**
* Perform action of waiting for a specific time. Useful when you need
* to wait for animations to end and Espresso fails at waiting.
* <p/>
* E.g.:
* onView(isRoot()).perform(waitAtLeast(Sampling.SECONDS_15));
*
* @param millis
* @return
*/
public static ViewAction waitAtLeast(final long millis) {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return anything();
}
@Override
public String getDescription() {
return "wait for at least " + millis + " millis.";
}
@Override
public void perform(final UiController uiController, final View view) {
uiController.loopMainThreadUntilIdle();
uiController.loopMainThreadForAtLeast(millis);
}
};
}
/**
* Perform action of waiting until UI thread is free.
* <p/>
* E.g.:
* onView(isRoot()).perform(waitUntilIdle());
*
* @return
*/
public static ViewAction waitUntilIdle() {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return anything();
}
@Override
public String getDescription() {
return "wait until UI thread is free";
}
@Override
public void perform(final UiController uiController, final View view) {
uiController.loopMainThreadUntilIdle();
}
};
}