简体   繁体   English

Android Espresso - 如果未选中,请单击复选框

[英]Android Espresso - Click checkbox if not checked

I have onView(withId(R.id.check_box)).perform(click()) , but i only want to do this if the check box is not already checked.我有onView(withId(R.id.check_box)).perform(click()) ,但我只想在尚未选中复选框的情况下执行此操作。 How can I do this in espresso?我怎样才能在浓缩咖啡中做到这一点?

I also wanted to toggle a checkbox/switch depending on it's previous state.我还想根据它以前的状态切换复选框/开关。 At first, I tried this to toggle ON a checkbox that was OFF:起初,我试着用这个来打开一个关闭的复选框:

onView(withId(R.id.checkbox)).check(matches(isNotChecked())).perform(scrollTo(), click());

...and this to toggle OFF a checkbox that was ON: ...这可以关闭一个打开的复选框:

onView(withId(R.id.checkbox)).check(matches(isChecked())).perform(scrollTo(), click());

However, this doesn't work, since Espresso will be looking for a specific toggle state before it performs the action.但是,这不起作用,因为 Espresso 将在执行操作之前寻找特定的切换状态。 Sometimes, you don't know whether it's ON or OFF beforehand.有时,您事先不知道它是打开还是关闭。

My solution is to use a custom ViewAction to turn OFF/ON any checkable object (Switch, Checkbox, etc.) that isn't dependent on previous state.我的解决方案是使用自定义 ViewAction 来关闭/打开任何不依赖于先前状态的可检查对象(开关、复选框等)。 So, if it's already ON, it'll stay ON.所以,如果它已经开启,它将保持开启。 If it's OFF, it'll toggle ON.如果它关闭,它将打开。 Here's the ViewAction:这是视图操作:

public static ViewAction setChecked(final boolean checked) {
    return new ViewAction() {
        @Override
        public BaseMatcher<View> getConstraints() {
            return new BaseMatcher<View>() {
                @Override
                public boolean matches(Object item) {
                    return isA(Checkable.class).matches(item);
                }

                @Override
                public void describeMismatch(Object item, Description mismatchDescription) {}

                @Override
                public void describeTo(Description description) {}
            };
        }

        @Override
        public String getDescription() {
            return null;
        }

        @Override
        public void perform(UiController uiController, View view) {
            Checkable checkableView = (Checkable) view;
            checkableView.setChecked(checked);
        }
    };
}

And here's how you use it (in this example, when you want to toggle to ON):这是您使用它的方式(在本例中,当您想切换到 ON 时):

onView(withId(R.id.toggle)).perform(scrollTo(), setChecked(true));

Just as @FrostRocket suggested but written in Kotlin.正如@FrostRocket 建议的那样,但用 Kotlin 编写。

We define a custom action that can only performed on checkable items (as specified in constraints).我们定义了一个只能对可检查项(如约束中指定)执行的自定义操作。 So we safely cast the view to Checkable to access setCheckable method.所以我们安全地将视图转换为 Checkable 以访问 setCheckable 方法。

fun setChecked(checked: Boolean) = object : ViewAction {
    val checkableViewMatcher = object : BaseMatcher<View>() {
        override fun matches(item: Any?): Boolean = isA(Checkable::class.java).matches(item)
        override fun describeTo(description: Description?) {
            description?.appendText("is Checkable instance ")
        }
    }

    override fun getConstraints(): BaseMatcher<View> = checkableViewMatcher
    override fun getDescription(): String? = null
    override fun perform(uiController: UiController?, view: View) {
        val checkableView: Checkable = view as Checkable
        checkableView.isChecked = checked
    }
}

This seems to be part of your test, that the checkbox needs to be checked.这似乎是您测试的一部分,需要选中复选框。

You can check this by:您可以通过以下方式检查:

onView(withId(R.id.checkbox)).check(matches(not(isChecked())));

If this fails, your test will fail, which may be good in your case.如果这失败了,你的测试就会失败,这对你来说可能是好的。 Then, you can perform the click you want after this case matches.然后,您可以在此案例匹配后执行您想要的点击。

If this is not the situation you want, can you explain more on what you are trying to do in this Espresso Test?如果这不是您想要的情况,您能否详细解释一下您在此 Espresso 测试中尝试做的事情?

You have something like this in your code:你的代码中有这样的东西:

@Rule
public ActivityTestRule<ActivityMain> ActivityMainRule = new ActivityTestRule<>(ActivityMain.class);

Try试试

if (!ActivityMainRule.getActivity().findViewById(R.id.check_box).isChecked()) {
    onView(withId(R.id.check_box)).perform(click())    
}

I had the same problem an wrote an own ViewAction that always unchecks my SwitchCompat我遇到了同样的问题,写了一个自己的 ViewAction,它总是取消选中我的 SwitchCompat

class UncheckViewAction implements ViewAction{

    @Override
    public Matcher<View> getConstraints() {
        return new Matcher<View>() {
            @Override
            public boolean matches(Object item) {
                return isA(SwitchCompat.class).matches(item);
            }

            @Override
            public void describeMismatch(Object item, Description mismatchDescription) {

            }

            @Override
            public void _dont_implement_Matcher___instead_extend_BaseMatcher_() {

            }

            @Override
            public void describeTo(Description description) {

            }
        };
    }

    @Override
    public String getDescription() {
        return null;
    }

    @Override
    public void perform(UiController uiController, View view) {
        SwitchCompat scView = (SwitchCompat) view;
        scView.setChecked(false);
    }
}

and used it like this:并像这样使用它:

onView(withId(R.id.check_box)).perform(new UncheckViewAction())

now i can be sure that the found switch is always unchecked, no matter if it was checked or unchecked before.现在我可以确定找到的开关总是未选中的,无论之前是选中还是未选中。

This simple solution might help you这个简单的解决方案可能会帮助你

onView(withId(R.id.checkBox_tea)).check(matches(isNotChecked())).perform(click()).check(matches(isChecked()));

worked perfectly for me.非常适合我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM