我对 Android 上的 Espresso 很陌生,我遇到了以下问题:我希望 Espresso 在按钮上执行长按(或其他操作),并且在按住按钮的同时,我想检查不同视图的状态.
I'm quite new to Espresso on Android and I am running into the following problem: I want Espresso to perform a longclick(or something..) on a button, and while the button is kept pressed down, I want to check the state of a different View.
在(或多或少)伪代码中:
In (more or less) pseudocode:
onView(withId(button_id)).perform(pressButtonDown());
onView(withId(textBox_id)).check(matches(withText("Button is pressed")));
onView(withId(button_id)).perform(releaseButton());
我尝试使用 MotionEvents.sendDown() 和 .sendUp() 编写 2 个自定义 Taps,PRESS 和 RELEASE,但没有成功.如果这是正确的路径,我可以发布到目前为止的代码.
I tried writing 2 custom Taps, PRESS and RELEASE, with MotionEvents.sendDown() and .sendUp(), but did not get it to work. If this is the right path, I can post the code I've got so far.
public class PressViewActions
{
public static ViewAction pressDown(){
return new GeneralClickAction(HoldTap.DOWN, GeneralLocation.CENTER, Press.THUMB);
}
public static ViewAction release() {
return new GeneralClickAction(HoldTap.UP, GeneralLocation.CENTER, Press.THUMB);
}
}
以及 Tappers 的代码:
And the code for the Tappers:
public enum HoldTap implements Tapper {
DOWN {
@Override
public Tapper.Status sendTap(UiController uiController, float[] coordinates, float[] precision)
{
checkNotNull(uiController);
checkNotNull(coordinates);
checkNotNull(precision);
DownResultHolder res = MotionEvents.sendDown(uiController, coordinates, precision);
ResultHolder.setController(uiController);
ResultHolder.setResult(res);
return Status.SUCCESS;
}
},
UP{
@Override
public Tapper.Status sendTap(UiController uiController, float[] coordinates, float[] precision)
{
DownResultHolder res = ResultHolder.getResult();
UiController controller = ResultHolder.getController();
try {
if(!MotionEvents.sendUp(controller, res.down))
{
MotionEvents.sendCancel(controller, res.down);
return Status.FAILURE;
}
}
finally {
//res.down.recycle();
}
return Status.SUCCESS;
}
}
}
我得到的错误如下:
android.support.test.espresso.PerformException: Error performing 'up click' on view 'with id: de.test.app:id/key_ptt'.
...
...
Caused by: java.lang.RuntimeException: Couldn't click at: 281.5,1117.5 precision: 25.0, 25.0 . Tapper: UP coordinate provider: CENTER precision describer: THUMB. Tried 3 times. With Rollback? false
我希望,这会有所帮助.
I hope, this helps.
我们将不胜感激任何帮助和想法!
Any help and ideas will be appreciated!
提前坦克很多!
Android 中的点击由两个事件组成,一个向下事件和一个向上/取消事件.如果您想将这两者分开,则不能进行点击",因为它们已经包含了两者.
A tap in Android is made up of two events, a down event and a up/cancel event. If you want to have these two as separate you cannot make "taps" as they already encompass both.
也就是说,你的想法行得通,你只需要使用一个较低级别的 api,即 UiController
以及 MotionEvents
中的辅助方法.但请注意:由于释放"视图需要首先持有它,如果您不进行适当的清理,您的测试将相互依赖.
That said, your idea works, you just need to use a lower-level api, namely UiController
along with the helper methods in MotionEvents
. Be warned though: since "releasing" a view requires first holding on it, your tests will be dependent on each other if you don't do proper clean up.
示例:在一个测试中,您按下一个视图,您的测试失败,然后在另一个测试中您在一个您未单击的视图上发布:您的第二个测试会通过,而它不应该通过.
Example: in a test you press a View, your test fails, then in another test you release on a view you didn't click: your second test would pass while it shouldn't have.
我在 我的 github 上上传了一个完整的示例.这里是关键点.首先是测试代码:
I uploaded on my github a complete sample. Here the keypoints. First the test code:
@Before
public void setUp() throws Exception {
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
getActivity();
}
@After
public void tearDown() throws Exception {
super.tearDown();
LowLevelActions.tearDown();
}
@Test
public void testAssertWhilePressed() {
onView(withId(R.id.button)).perform(pressAndHold());
onView(withId(R.id.text)).check(matches(withText("Button is held down")));
onView(withId(R.id.button)).perform(release());
}
然后是 LowLevelActions:
Then LowLevelActions:
public class LowLevelActions {
static MotionEvent sMotionEventDownHeldView = null;
public static PressAndHoldAction pressAndHold() {
return new PressAndHoldAction();
}
public static ReleaseAction release() {
return new ReleaseAction();
}
public static void tearDown() {
sMotionEventDownHeldView = null;
}
static class PressAndHoldAction implements ViewAction {
@Override
public Matcher<View> getConstraints() {
return isDisplayingAtLeast(90); // Like GeneralClickAction
}
@Override
public String getDescription() {
return "Press and hold action";
}
@Override
public void perform(final UiController uiController, final View view) {
if (sMotionEventDownHeldView != null) {
throw new AssertionError("Only one view can be held at a time");
}
float[] precision = Press.FINGER.describePrecision();
float[] coords = GeneralLocation.CENTER.calculateCoordinates(view);
sMotionEventDownHeldView = MotionEvents.sendDown(uiController, coords, precision).down;
// TODO: save view information and make sure release() is on same view
}
}
static class ReleaseAction implements ViewAction {
@Override
public Matcher<View> getConstraints() {
return isDisplayingAtLeast(90); // Like GeneralClickAction
}
@Override
public String getDescription() {
return "Release action";
}
@Override
public void perform(final UiController uiController, final View view) {
if (sMotionEventDownHeldView == null) {
throw new AssertionError("Before calling release(), you must call pressAndHold() on a view");
}
float[] coords = GeneralLocation.CENTER.calculateCoordinates(view);
MotionEvents.sendUp(uiController, sMotionEventDownHeldView, coords);
}
}
}
这篇关于Android Espresso:按住按钮时进行断言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!