简介
奈何桥上叹奈何, 三生石前憾三生, 彼岸花下非彼岸, 奈何三生彼岸人.
相传过了鬼门关便上一条路叫黄泉路, 路上盛开着只见花, 不见叶的彼岸花. 花叶生生两不见, 相念相惜永相失, 路尽头有一条河叫忘川河, 河上有一座桥叫奈何桥. 走过奈何桥有一个土台叫望乡台. 望乡台边有个亭子叫孟婆亭, 有个叫孟婆的女人守候在那里, 给每个经过的路人递上一碗孟婆汤. 忘川河边有一块石头叫三生石. 喝下孟婆汤让人忘了一切. 三生石记载着前世今生来世.
人死先到鬼门关, 出了鬼门关, 途经黄泉路, 来到忘川河边, 便是奈何桥. 奈何桥上有孟婆, 要过奈何桥, 就要喝孟婆汤, 不喝孟婆汤, 就过不得奈何桥, 过不得奈何桥, 就不得投生转世. 凡是喝过孟婆汤的人就会忘却今生今世所有的牵绊, 了无牵挂地进入轮回道开始了下一世的轮回.
孟婆汤又称忘情水或忘忧散, 一喝便忘前世今生. 阳间的每个人在这里都有自己的一只碗, 碗里的孟婆汤, 其实就是活着的人一生所流的泪. 每个人活着的时候, 都会落泪: 因喜, 因悲, 因痛, 因恨, 因愁, 因爱. 孟婆将他们一滴一滴的泪收集起来, 煎熬成汤, 在他们离开人间, 走上奈何桥头的时候, 让他们喝下去, 忘却活着时的爱恨情愁, 干干净净, 重新进入六道, 或为仙, 或为人, 或为畜. 不是每个人都会心甘情愿地喝下孟婆汤.
因为这一生, 总会有爱过的人不想忘却. 孟婆会告诉他: 你为她一生所流的泪都熬成了这碗汤, 喝下它, 就是喝下了你对她的爱. 来的人眼中最后的一抹记忆便是他今生挚爱的人, 喝下汤, 眼里的人影慢慢淡去, 眸子如初生婴儿般清彻. 为了来生再见今生最爱, 你可以不喝孟婆汤, 那便须跳入忘川河, 等上千年才能投胎. 千年之中, 你或许会看到桥上走过今生最爱的人, 但是言语不能相通, 你看得见她, 她看不见你.
千年之中, 你看见她走过一遍又一遍奈何桥, 喝过一碗又一碗孟婆汤, 你盼她不喝孟婆汤, 又怕她受不得忘川河中千年煎熬之苦. 千年之后若心念不灭, 还能记得前生事, 便可重入人间, 去寻前生最爱的人. 奈何桥边有块青石叫三生石, 三生石记载着每个人的前世今生, 石身上的字鲜红如血, 最上面刻着四个大字 "早登彼岸".
溜冰是香港目前流行的叫法, 而国内则叫旱冰或轮滑, 台湾称为溜冰, 澳门则叫它做雪屐. 不论叫法如何, 其目的只是区别水冰地面或非水冰地面 (ICE SKATING). 然而在宏哥这宏哥把手机上的这种滑动称其为溜冰, 咱也当一回文艺人.
今天做自动化设置手势密码 9 宫格, 本以为发现 swipe 不能满足需求, 于是用 TouchAction 去实现手势滑动. 但是不是想象中的那么顺利.
这篇文章写的特别的痛苦, 写的死去活来, 期间多次想放弃, 但是最终坚持下来了, 破茧成蝶, 写的宏哥好像真的是奈何桥上走了一遭,. 细心地小伙伴们或者童鞋们会发现宏哥已经好多天没有更新文章了. 那是因为这篇文章中遇到了不少坑, 耗费了大量时间, 总的来说大约是两个晚上的时间, 每晚上大约 3 到 4 个小时. 下边慢慢的听宏哥给你一一道来.
高级溜冰的滑动
滑动操作一般是两点之间的滑动, 这种滑动宏哥在这里称其为低级的溜冰滑动; 就是宏哥上一节给小伙伴们分享的. 然而实际使用过程中用户可能要进行一些多点连续滑动操作. 如九宫格滑动操作, 连续拖动图片移动等场景. 那么这种高级绚丽的溜冰滑动在 Appium 中该如何模拟这类操作呢? 下面听宏哥给你慢慢道来.
TouchAction
首先看一下官方文档
地址: https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.touch_actions.html
Touch Action 包含一些列操作, 比如按压, 长按, 点击, 移动, 暂停. 由着些不同操作可以组成一套动作. 使用 TochAction 需要先导入对应的模块
from appium.webdriver.common.touch_action import TouchAction
按压
方法: press() 开始按压一个元素或坐标点(x,y). 通过手指按压手机屏幕的某个位置. press 也可以接收屏幕的坐标(x,y).
- press(self, el=None, x=None, y=None)
- TouchAction(driver).press(x=0,y=308)
长按
方法: longPress() 开始按压一个元素或坐标点 (x,y). 相比 press() 方法, longPress()多了一个入参, 既然长按, 得有按的时间吧. duration 以毫秒为单位. 1000 表示按一秒钟. 其用法与 press()方法相同.
long_press(self, el=None, x=None, y=None, duration=1000)
点击
方法: tap() 对一个元素或控件执行点击操作. 用法参考 press().
tap(self, element=None, x=None, y=None, count=1)
移动
方法: move_to() 将指针从上一个点移动到指定的元素或点.
move_to(self, el=None, x=None, y=None)
注意:
移动到目位置有时是算绝对坐标点, 有时是基于前面一个坐标点的偏移量, 这个要结合具体 App 来实践.
暂停
方法: Wait()
wait(self, ms=0)
暂停脚本的执行, 单位为毫秒.
释放
方法: release() 结束的行动取消屏幕上的指针.
release(self)
执行
方法: perform() 执行的操作发送到服务器的命令操作.
perform(self)
TouchAction 实战 -- 九宫格滑动操作
九宫格是一种比较常见的图案加密方式, 目前很多 App 都支持设置图案锁, Android 原生系统也支持设九宫格图案锁屏. 那么我们该如何使用 Appium 进行滑动操作呢?
测试场景
安装启动随手记 App 启动 App 后在密码设置选项中开启手机密码并滑动九宫格设置如下 "Z" 字形的图形密码.
测试环境
1. 宏哥的系统环境是 Windows 10 版本 64 位系统
2. 宏哥的 dk 版本:"1.8.0_181"
3. 宏哥的 appium 版本: 1.4.16
4.selenium:3.141.0
安装 selenium:
输入指令 pip install selenium
验证安装成功: pip show selenium
5. 测试设备: Android 5.1.1 (不能低于 5.0 版本)
6.Python:3.7.2
命令: python -V , 回车即可.
7. 测试 App: 随手记 Android App V9.7.1.5
想法与思路
安装启动随手记 App
代码实现点击 "下一步", 向左滑动首页引导页面
点击 "开始随手记" 进入首页页面
点击 "设置" 按钮, 向上滑动, 找到 "高级" 按钮, 点击进入
点击 "手势密码", 开始设置手势密码(高级滑动)
代码实现
(1)安装启动随手记
(2)代码实现点击 "下一步", 向左滑动首页引导页面
(3)点击 "开始随手记" 进入首页页面
(4)点击 "设置" 按钮, 向上滑动, 找到 "高级" 按钮, 点击进入
(5)点击 "手势密码", 开始设置手势密码, 进行解锁(高级滑动)
这个地方 move_to 到了按下的这个坐标点, 是因为不这样的话实际结果忽略掉了第一个按下的点. release()释放, perform()执行.
代码运行结果
运行过程 appium 和夜神模拟器
参考代码
- # coding=utf-8
- # 1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- # 2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-8-07
- @author: 北京 - 宏哥 QQ 交流群: 707699217
- Project: 学习和使用 appium 自动化测试 - 高级滑动
- '''
- # 3. 导入模块
- from appium import webdriver
- from appium.webdriver.common.touch_action import TouchAction
- from selenium.webdriver.support.ui import WebDriverWait
- from selenium.common.exceptions import NoSuchElementException
- from time import sleep
- desired_caps={}
- desired_caps['platformName']='Android'
- desired_caps['deviceName']='127.0.0.1:62001'
- desired_caps['platforVersion']='5.1.1'
- desired_caps['app']=r'C:\Users\DELL\Downloads\mymoney.apk'
- desired_caps['appPackage']='com.mymoney'
- desired_caps['appActivity']='com.mymoney.biz.splash.SplashScreenActivity'
- driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)
- driver.implicitly_wait(5)
- def get_size():
- x=driver.get_window_size()['width']
- y=driver.get_window_size()['height']
- return x,y
- def swipeLeft():
- l=get_size()
- x1=int(l[0]*0.9)
- y1=int(l[1]*0.5)
- x2=int(l[0]*0.1)
- driver.swipe(x1,y1,x2,y1,1000)
- def swipeUp():
- l = get_size()
- x1 = int(l[0] * 0.5)
- y1 = int(l[1] * 0.95)
- y2 = int(l[1] * 0.35)
- driver.swipe(x1, y1, x1, y2, 1000)
- #等待启动页面元素, 然后向左滑动两次, 跳过引导页面
- WebDriverWait(driver,6).until(lambda x:x.find_element_by_id('com.mymoney:id/next_btn'))
- for i in range(2):
- swipeLeft()
- sleep(0.5)
- #点击 "开始随手记" 按钮
- driver.find_element_by_id('com.mymoney:id/begin_btn').click()
- #检测是否有活动页面弹窗, 如果有就点击关闭
- try:
- closeBtn=driver.find_element_by_id('com.mymoney:id/close_iv')
- except NoSuchElementException:
- pass
- else:
- closeBtn.click()
- #点击设置
- driver.find_element_by_id('com.mymoney:id/nav_btn_forth').click()
- #等待界面菜单加载出来, 然后向上滑动
- WebDriverWait(driver,6).until(lambda x:x.find_element_by_id('android:id/content'))
- swipeUp()
- #点击高级菜单
- driver.find_element_by_android_uiautomator('new UiSelector().text(" 高级 ")').click()
- #点击密码与手势密码菜单
- driver.find_element_by_id('com.mymoney:id/password_protect').click()
- #点击手势密码保护
- driver.find_element_by_id('com.mymoney:id/ll_gesture_psd').click()
- #连续滑动两次设置图案密码
- for i in range(2):
- TouchAction(driver).press(x=212, y=296).wait(100)\
- .move_to(x=148, y=0).wait(100)\
- .move_to(x=148,y=0).wait(100)\
- .move_to(x=-148,y=148).wait(100)\
- .move_to(x=-148,y=148).wait(100)\
- .move_to(x=148,y=0).wait(100)\
- .move_to(x=148,y=0).wait(100) \
- .release().wait(200).perform()
连续滑动设置手势密码坐标计算
首先使用工具获取到元素坐标位置, 可以看到起始位置是[138,218] , 终点位置是[581,661]
分析:
该图形可以横竖划分六等分
那么第一个圆中心点的坐标:
- x=138+(581-138)/6
- y=218+(661-218)/6
依次类推, 想要画一个 z 形状, 则需要计算第 1,2,3,5,7,8,9 这几个圆的中心点坐标
然后用 TouchAction 的 press 和 moveto 方法将几个步骤链接起来. 代码如下
- # 引入包
- from appium.webdriver.common.touch_action import TouchAction
- def settingPassword(self):
- #[138,218][581,661]夜神上的元素坐标
- xxx = (581-138) / 6
- one_x = 138 + xxx
- one_y = 218 + xxx
- two_x = 138 + xxx * 3
- two_y = 218 + xxx #与第二个纵坐标相等
- three_x=138 + xxx*5
- three_y=218 + xxx #与第二个纵坐标相等
- five_x=138 + xxx * 3
- five_y=218+xxx*3
- seven_x=138 + xxx
- seven_y=218+xxx*5
- eight_x=138 + xxx * 3
- eight_y=218+xxx*5
- nine_x=138 + xxx*5
- nine_y=218+xxx*5
- TouchAction(self.driver).press(x=one_x, y=one_y).wait(300).move_to(x=two_x, y=two_y).wait(300).move_to(x=three_x,y=three_y).wait(300).move_to(x=five_x,y=five_y).wait(300).move_to(x=seven_x,y=seven_y).wait(300).move_to(x=eight_x,y=eight_y).wait(300).move_to(x=nine_x,y=nine_y).release().perform()
小结
1. 实现的时候总是报错:
The coordinates provided to an interactions operation are invalid.
解决方案: 在 release 后边加上 wait, 即可. 这可是宏哥查了好多资料, 才找到的解决办法, 具体原因宏哥也有点蒙圈, 等找到原因了, 后期补上, 或者有知道的大佬可以分享一下心得体会 .
期间宏哥想不用 for 循环了, 直接写了两个一样的 TouchAction 还是报错, 然后宏哥实在是搞不定了, 第二天晚上宏哥决定既然可以画一个 Z 字形, 要不把设置密码的文章改成解锁密码文章 , 前者需要画两个 Z 字形, 后者需要画一个 Z 字形. 而且刚好解锁, 需要一个就可以, 内心的小鬼在打架, 最终还是理性打败了取巧和任性, 硬着头皮解决遇到的各种问题, 才有了这篇文章的产生. 这也侧面的反应学习和工作是不能偷奸取巧的.
- for i in range(2):
- TouchAction(driver).press(x=212, y=296).wait(100)\
- .move_to(x=148, y=0).wait(100)\
- .move_to(x=148,y=0).wait(100)\
- .move_to(x=-148,y=148).wait(100)\
- .move_to(x=-148,y=148).wait(100)\
- .move_to(x=148,y=0).wait(100)\
- .move_to(x=148,y=0).wait(100) \
- .release().wait(100).perform()
2. 这段代码里面有俩个坑, 呃, 关键点:
(1)press 方法中的坐标为绝对坐标, move_to 方法中的坐标都是相对坐标, 具体来说第一个 move_to 中的坐标相对于 press 方法中的坐标, 第二个 move_to 方法中的坐标相对于第一个 move_to 方法中的坐标. 以此类推下去, 以前好像不是这个样子的. 直接计算完就可以用了. 宏哥期间犯的错误:
a. 就是直接算完就用结果报错; 然后查资料说是相对坐标;
b. 然后把后边 move_to 的坐标都相对第一个绝对坐标了, 结果可想而知, 还是报错.
继续查资料, 才找到以上的解决办法了.
(2)wait 是必须的: 这里 ms 表示为毫秒, ms=100 就是等待 100 毫秒. 不用的话太快会出错
3. 分成六等份, 小伙伴们有点蒙圈, 给小伙伴们看一幅比较直观的图
4. 好了, 奈何桥走了一遭, 终于搞定了, 获得了新生. 不过遗憾的事是: 实在太忙了, 写文章, 解决问题和各种坑, 没来得及喝一碗孟婆汤, 不知道它的味道是酸甜苦辣...., 还是其他什么味道, 然后把这个痛苦的过程忘记掉. 友情提示: 小伙伴们和童鞋们如果滑到奈何桥, 可以喝一碗尝一尝鲜.
最后, 今天是七夕节, 祝大家七夕节快乐, 吃好, 玩好!!!
您的肯定就是我进步的动力. 如果你感觉还不错, 就请鼓励一下吧! 记得点波 推荐 哦!!!(点击右边的小球即可! :))
个人公众号 微信群 (微信群已满 100, 可以加宏哥的微信拉你进群) 宏哥微信(请备注: 进群)
来源: https://www.cnblogs.com/du-hong/p/11302187.html