Appium appium 的 move_to 相对坐标?绝对坐标?

张璐 · 2016年02月16日 · 最后由 xujuan 回复于 2016年09月20日 · 3814 次阅读
action.press(x=252, y=879).wait(10000).move_to(x=540, y=879).release().perform()
print '1'
action.press(x=252, y=879).move_to(x=540, y=879).wait(10000).release().perform()
print '2'
action.press(x=D['b1']['x'], y=D['b1']['y']).wait(10000).move_to(x=D['b2']['x'], y=D['b2']['y']).release().perform()
print '3'
action.press(None,D['b1']['x'],D['b1']['y']).wait(10000).move_to(None,D['b2']['x'],D['b2']['y']).wait(800).move_to(None,D['b5']['x'],D['b5']['y']).wait(800).move_to(None,D['b8']['x'],D['b8']['y']).wait(800).move_to(None,D['b9']['x'],D['b9']['y']).release().perform()
print '4'

1 和 2 的代码只是等待放置的位置不同,但是执行结果完全不一样,第一个取到的是绝对坐标绘制正确
2 代码会提示坐标超出象限找不到,认为取的是相对坐标
3 的执行结果和 1 一致,但是为何加了几个坐标点 4 就执行错误了?看到的表象和 2 一样,第二个点就没有找到。
有人可以解答一下吗?困惑好几天了。

共收到 19 条回复 时间 点赞
19楼 已删除

如果你加入 TesterHome 的群, 就不会困惑这么久了。
在 moveTo 后面直接加 release,就会解析成 dragApp,就是用的绝对坐标
在 moveTo 后面还有 wait 的话,就是偏移量~

asdaasdadassddsad

我来具体解释下,可能说明的不太清楚,因为主要这里的逻辑都是 Appium server 进行处理的。我对 node.js 不太懂,今晚勉勉强强调试了好久。。。
首先先看第一个

action.press(x=252, y=879).wait(10000).move_to(x=540, y=879).release().perform()

我们首先分析 Server 的 log,显示的是

POST /wd/hubssion/063350c4-bd8c-4a7c-ac0c-96e35075f1d2/touch/perform {"sessionId":"063350c4-bd8c-4a7c-ac0c-96e35075f1d2","actions":[{"action":"press","options":{"y":879,"x":252}},{"action":"wait","options":{"ms":10000}},{"action":"moveTo","options":{"y":879,"x":540}},{"action":"release","options":{}}]}

我们首先看 controller.js 312

这里 Server 会解析出一个 gestures 的数组里面包含了前面的 4 个 action。

if (gestures.length === 4 &&
      gestures[0].action === 'press' &&
      gestures[1].action === 'wait' &&
      gestures[2].action === 'moveTo' &&
      gestures[3].action === 'release') {
      return exports.mobileSwipe(req, res, gestures);
  }

上面这个代码就可以看出 我们的脚本直接转换成了 swipe 的操作了。下来看看 swipe 的操作 497 行

var touchCount = req.body.touchCount || 1
   , startX =  getCoordDefault(gestures[0].options.x)
   , startY = getCoordDefault(gestures[0].options.y)
   , endX = getCoordDefault(gestures[2].options.x)
   , endY = getCoordDefault(gestures[2].options.y)
   , duration = _getSwipeTouchDuration(gestures[1])
   , element = gestures[0].options.element
   , destElement = gestures[2].options.element || gestures[0].options.element;

这里就能够看出操作的是绝对坐标

那再来我们看看第二个。
还是一样 看看 Server 的输出吧

{"sessionId":"dfc437da-3ad5-49c1-8944-ed408fbbb73c","actions":[{"action":"press","options":{"y":879,"x":252}},{"action":"moveTo","options":{"y":879,"x":540}},{"action":"wait","options":{"ms":10000}},{"action":"release","options":{}}]}

因为这个顺序是不满足 swipe 的所以直接走的是
android-controller.js 中的 865 行 performTouch

这边 Server 的大体流程是会先将所有的命令,action 都解析然后逐个进行操作。

performTouch 中会执行下面的 parseTouch

// fix release action then perform all actions
   fixRelease(function (err) {
     if (err) return cb(err);
     this.parseTouch(gestures, false, function (err, fixedGestures) {
       if (err) return cb(err);
       async.eachSeries(fixedGestures, performGesture, cb);
     });
   }.bind(this));

所以我们还得看下 parseTouch 做了什么。

这里的代码很长我就不贴出来了,这里还是前面说的解析命令 将每个 action 的命令解析结果都存储在 touchStateObjects 这个数组里面。

touchStateObjects.push(touchStateObject);

之后就是遍历这个数组,逐个执行了。

 var prevPos = null,
_.each(touchStateObjects, function (state) {
      if (typeof state.options.x === 'undefined' && typeof state.options.x === 'undefined') {
        // this happens with wait
        state.options.x = prevPos.x;
        state.options.y = prevPos.y;
      }
      if (state.options.offset && prevPos) {
        // the current position is an offset
        state.options.x += prevPos.x;
        state.options.y += prevPos.y;
      }
      delete state.options.offset;
      prevPos = state.options;

      ....
    });

仔细看看就能够知道,首先执行 press 操作,这个时候的 prevPos 是为 null 的 所以 x,y 坐标不会改变,接着会执行 prevPos = state.options,所以到下一个 moveTo 的时候 就会执行到

state.options.x += prevPos.x;
state.options.y += prevPos.y;

所以 MoveTo 的坐标就变成了 x=792.0, y=1758.0
所以就会出现 Server 的 log 如下

Returning result: {"value":"Coordinate [x=792.0, y=1758.0] is outside of element rect: [0,0][768,1184]","status":29}

出现越界的情况了。

以上就是我分析的大概情况了。可能有点不太正确。

张璐 #20 · 2016年02月17日 Author

#2 楼 @lylyliuyu 非常感谢答复,但是我将 wait 去除,完全只有 move 后面加 release 执行结果也是错误的,能帮忙再看下吗?感谢。

action.press(x=252, y=879).move_to(x=540, y=879).move_to(x=540, y=1167).move_to(x=540, y=1455).move_to(x=828, y=1455).release().perform()

#4 楼 @zsx10110 非常感谢,解释的很清楚,那我手势密码多个 move_to 的过程只能用相对坐标了……难道就没有连续 move 的是绝对坐标么?好奇怪呀……

#2 楼 @lylyliuyu 我发的消息还是有人关注的,挺开心呀😄

#6 楼 @spiritzl https://testerhome.com/topics/1809 看看这篇文章 里面有手势解锁。

#2 楼 @lylyliuyu 23333 我还上镜了

#5 楼 @spiritzl 我只是个大自然的搬运工。。 这个方法我没用过。。 只是看到过

#7 楼 @weamylady
#9 楼 @neyo

经常在群里看, 学习到不少:)

#11 楼 @lylyliuyu 群号给个?我只入了公开课的那个群

#11 楼 @lylyliuyu 跟你学到不少😄


楼上各位谁知道一个错怎么解决

#2 楼 @lylyliuyu 请问 python 执行后为何一直提示 AttributeError: 'NoneType' object has no attribute 'execute'

#2 楼 @lylyliuyu 如果想实现向上 滑动,通过 TouchAction(self.driver).press(x=100,y=800).move_to(x=0,y=-50) 仍无法实现。请教是什么原因

#17 楼 @lovingjune 负值 这个解决了么? 我也遇到 相同的问题, 界面 上看已经成功滑动了, 但是最后还是报错。既然是相对坐标,为什么不能有负值 呢??

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册