Automating number picker in android using espresso
There is a problem with accepted answer : it does not fire on change event. So (if you need it) you can't test if your view react to this on change event.
The following code (kotlin) is not cool anyway but i think it's the only way.
fun setValue(value: Int): ViewAction {
return object : ViewAction {
override fun getDescription(): String {
return "set the value of a " + NumberPicker::class.java.name
}
override fun getConstraints(): Matcher<View> {
return ViewMatchers.isAssignableFrom(NumberPicker::class.java)
}
// the only way to fire onChange event is to call this private method
override fun perform(uiController: UiController?, view: View?) {
val numberPicker = view as NumberPicker
val setValueMethod = NumberPicker::class.java.getDeclaredMethod(
"setValueInternal",
Int::class.java,
Boolean::class.java
)
setValueMethod.isAccessible = true
setValueMethod.invoke(numberPicker, value, true)
}
}
}
For those looking at this question later (like me) this might be helpful: DateTimePickerTest makes use of PickerActions. PickerActions allows code for date pickers like this (Java):
onView(withClassName(Matchers.equalTo(DatePicker.class.getName()))).perform(PickerActions.setDate(year, month + 1, day));
Or for time pickers (Kotlin):
onView(withClassName(Matchers.equalTo(TimePicker::class.java.name))).perform(PickerActions.setTime(0, 10))
Match the view and then perform the action:
ViewInteraction numPicker = onView(withClassName(Matchers.equalTo(NumberPicker.class.getName())));
numPicker.perform(setNumber(1));
Create a ViewAction to set the number:
public static ViewAction setNumber(final int num) {
return new ViewAction() {
@Override
public void perform(UiController uiController, View view) {
NumberPicker np = (NumberPicker) view;
np.setValue(num);
}
@Override
public String getDescription() {
return "Set the passed number into the NumberPicker";
}
@Override
public Matcher<View> getConstraints() {
return ViewMatchers.isAssignableFrom(NumberPicker.class);
}
};
}
To match a View by its class name you can simply use:
onView(withClassName(Matchers.equalTo(TimePicker.class.getName())));
Once you have the ViewInteraction object you can set a value on it defining and using a ViewAction as following:
public static ViewAction setTime(final int hour, final int minute) {
return new ViewAction() {
@Override
public void perform(UiController uiController, View view) {
TimePicker tp = (TimePicker) view;
tp.setCurrentHour(hour);
tp.setCurrentMinute(minute)
}
@Override
public String getDescription() {
return "Set the passed time into the TimePicker";
}
@Override
public Matcher<View> getConstraints() {
return ViewMatchers.isAssignableFrom(TimePicker.class);
}
};
}