简介 


  今天宏哥在这里首先给小伙伴们和童鞋们分享一个有关昙花的小典故:话说昙花原是一位花神,她每天都开花,四季都灿烂。她还爱上了每天给她浇水除草的年轻人。后来,此事给玉帝得知。于是,玉帝大发雷霆,要拆散鸳鸯。他将花神抓了起来,把她贬为每年只能开一瞬间的昙花,不让她再和情郎相见,还把那年轻人送去灵鹫山出家,赐名韦陀,让他忘记前尘,忘记花神。

  多年过去了,韦陀果真忘了花神,潜心习佛,渐有所成。而花神却怎么也忘不了那个曾经照顾她的小伙子。她知道每年暮春时分,韦陀总要下山来为佛祖采集朝露煎茶。所以,昙花就选择在那个时候开放。她把集聚了整整一年的精气绽放在那一瞬间,希望韦陀能回头看她一眼,能记起她。可是,千百年间过去了,韦陀一年年的下山来采集朝露,昙花一年年的默默绽放,韦陀始终没有记起她。直到有一天,一名枯瘦的男子从昙花身边走过,看到花神忧郁孤苦之情,便停下脚步问花神:“你为什么哀伤?”。花神惊异,因为凡人是看不到花神的真身。如果是大罗金仙头上有金光、如果是妖魔头上有黑气、如果而凡人头上是无任何灵光。刚刚从身边走过的明明是一个凡人,如何看得见自己的真身。花神犹豫片刻,只是答到:“你帮不了我”。又默默等待韦陀,不再回答那个男子的话。40年后,那个枯瘦男子又从昙花身边走过,重复问了40年前的那句话:“你为什么哀伤?”花神再次犹豫片刻,只是答道“你也许帮不了我”。枯瘦的男子笑了笑离开。再40年后,一个枯瘦的老人再次出现在花神那里,原本枯瘦的老人看起来更是奄奄一息。当年的男子已经变成老人,但是他依旧问了和80年前一样的话:“你为什么哀伤?”。昙花答道:“谢谢你这个凡人,在你一生问过我3次,但是你毕竟是凡人,而且已经奄奄一息,还怎么帮我,我是因爱而被天罚的花神”。老人笑了笑,说“我是聿明氏,我只是来了断80年前没有结果的那段缘分。花神,我只送你一句‘缘起缘灭缘终尽、花开花落花归尘’”。说完老人闭目坐下。时间渐渐过去,夕阳的最后一缕光线开始从老人的头发向眼睛划去。老人笑道:“昙花一现为韦陀,这般情缘何有错,天罚地诛我来受,苍天无眼我来开”。说罢,老人一把抓住花神。此时的夕阳正好滑到了老人的眼睛,老人随即圆寂,抓着花神一同去往佛国去。花神在佛国见到了韦陀,韦陀也终于想起来前世因缘。佛祖知道后准韦陀下凡了断未了的因缘。
  昙花一现,只为韦陀。所以,昙花又名韦陀花。也因为昙花是在夕阳后见到韦陀,所以昙花都是夜间开放。
  好了,到此故事结束了,开始今天的主题 - 获取toast提示

在日常使用App过程中,经常会看到App界面有一些弹窗提示(如下图所示)这些提示元素出现后等待3秒左右就会自动消失,这个和我日常生活中看到的烟花和昙花是多么的相似,那么我们该如何获取这些元素文字内容呢?

 

Toast简介

Android中的Toast是一种简易的消息提示框。 当视图显示给用户,在应用程序中显示为浮动。和Dialog不一样的是,它永远不会获得焦点,无法被点击。

Toast类的思想就是尽可能不引人注意,同时还向用户显示信息,希望他们看到。而且Toast显示的时间有限,一般3秒左右就消失了。因此使用传统的元素定位工具,我们是无法定位到Toast元素的(传说中低调奢华有内涵)。

Appium Toast内容获取

Add ability to verify TOAST messages (these can't be interacted with, only
text retrieval allowed)
1.Appium 1.6.3开始支持识别Toast内容,主要是基于UiAutomator2,因此需要在Capablity配置如下参数:
'automationName':'uiautomator2' 或者: desired_caps['automationName']='
uiautomator2'
2.安装appium-uiautomator2-driver: 安装命令如下:
cnpm install appium-uiautomator2-driver


安装成功后可以在 C:\Users\Administrator\node_modules看到对应的文件:
[email protected]@appium-uiautomator2-driver _appium
[email protected]@appium-uiautomator2-server


测试环境

1.宏哥的系统环境是Windows 10版本 64位系统



 

2.j宏哥的dk版本:"1.8.0_181"



3.宏哥的appium版本:1.4.16 



经查询appium1.6.3以上才能识别toast,之前安装appium版本是1.4.X,于是重整了测试环境

官方文档是这么说的

Firstly you should install appium server. Appium getting started
<http://appium.io/getting-started.html>. The version 1.6.3 or greater is
recommended.

Since version 5.x there many features based on Java 8. So we recommend to
install JDK SE 8 and provide that source compatibility.

也就是更新appium
到1.6.3以上,java-client版本最好是5.x,jdk要用1.8、selenium要用3.x,其他版本不一定兼容,要自己亲测是否可用

想识别toast,官网是这么说,因此为了不必要的麻烦折腾环境最好还是卸载低版本的appium,然后安装版本高于1.6.3的appium。

appium有两种安装方式,看你的需要选择方法一或方法二

        方法一:

     
使用下载地址:https://bitbucket.org/appium/appium.app/downloads/,可以下载exe应用,桌面程序,更适合新手,界面设置,更容易上手,但是目前appium已经更新1.6.3+,以上下载地址还没更新最新的上去。如果不使用UIAUTOMATOR2等appium提供的新功能,不需要下载比较新的ppium,

        方法二:

      已安装了node.js,可以使用npm命令安装appium,打开cmd,输入npm install -g
appium,回车,即可开始安装目前最新的版本,速度会比较慢,毕竟是国外的,如果不安装最新的使用命令:npm install -g
[email protected],xxx是版本号,如下载appium1.6.3,命令为npm install -g
[email protected],我是一开始使用方法一,之后发现几个功能appium要更新到1.6.3以上才支持,所以我目前版本更新到了1.6.3+以上。



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 V3.1.0
8.测试场景
进入登录界面输入错误的用户名或者密码,获取Toast内容:

“用户名或密码错误,你还可以尝试4次”
“验证失败次数过多,请15分钟后再试”

代码实现

步骤一:初始化

在capability配置内部增加:desired_caps[‘uiautomationName’]=’ uiautomator2’

步骤二:定位toast元素

(1)定义toast文本内容

(2)定义路径

(3)组合文本内容和路径进行定位:用format()连接路径和文本内容


参考代码
1 # coding=utf-8 2 # 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行 3 4 # 2
.注释:包括记录创建时间,创建人,项目名称。 5 ''' 6 Created on 2019-7-31 7 @author: 北京-宏哥 QQ交流群:
707699217 8 Project:学习和使用appium自动化测试-toast提示 9 ''' 10 # 3.导入模块 11 from appium
import webdriver12 from selenium.common.exceptions import NoSuchElementException
13 from selenium.webdriver.support.ui import WebDriverWait 14 from
selenium.webdriver.support import expected_conditionsas EC 15 16 desired_caps =
{'platformName': 'Android', 17 'platforVersion': '5.1.1', 18 'automationName': '
Uiautomator2', 19 'deviceName': '127.0.0.1:62001', 20 'app': r'
C:\Users\DELL\Downloads\kaoyanbang.apk', 21 'appPackage': 'com.tal.kaoyan', 22 '
appActivity': 'com.tal.kaoyan.ui.activity.SplashActivity', 23 'noReset': 'True'}
24 25 driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) 26
driver.implicitly_wait(9) 27 try: 28 driver.find_element_by_id("
android:id/button2").click() 29 except NoSuchElementException: 30 print(1) 31
try: 32 driver.find_element_by_id('com.tal.kaoyan:id/tv_skip').click() 33
except NoSuchElementException:34 print(2) 35 driver.find_element_by_id('
com.tal.kaoyan:id/login_email_edittext').clear() 36 driver.find_element_by_id('
com.tal.kaoyan:id/login_email_edittext').send_keys('bjhongge') 37 38
driver.find_element_by_id('com.tal.kaoyan:id/login_password_edittext'
).send_keys('1213213') 39 driver.find_element_by_id('
com.tal.kaoyan:id/login_login_btn').click() 40 41 error_message = "
用户名或密码错误,你还可以尝试3次" 42 limit_message = "验证失败次数过多,请15分钟后再试" 43 44 message = '
//*[@text=\'{}\']'.format(error_message) 45 #message='//*[@text=\'{}\']'
.format(limit_message)46 47 toast_element = WebDriverWait(driver, 15
).until(lambda x:x.find_element_by_xpath(message))48 print(toast_element.text)
说明:

连接不同的类型的变量或内容format()

显示等待:webdriver(driver,5)

driver是webdriver的驱动程序,5是超时时间,以秒为单位

WebDriverWait()一般由 until()或 until_not()方法配合使用,下面是 until()和 until_not()方法的说明。

until(method, message=’’)

调用该方法提供的驱动程序作为一个参数,直到返回值不为 False。

until_not(method, message=’’)

调用该方法提供的驱动程序作为一个参数,直到返回值为 False。
 

动态函数:lambda x:x+5  

       X是函数的参数,冒号后面是函数的返回值

封装toast判断

1.单独写一个函数来封装判断是否存在toast消息,存在返回True,不存在返回False
1 def is_toast_exist(driver,text,timeout=30,poll_frequency=0.5): 2 3 '''is
toast exist, return True or False 4 5 :Agrs: 6 7 - driver - 传driver 8 9
- text - 页面上看到的文本内容 10 11 - timeout - 最大超时时间,默认30s 12 13 - poll_frequency -
间隔查询时间,默认0.5s查询一次14 15 :Usage: 16 17 is_toast_exist(driver, "看到的内容") 18 19 '''
20 21 try: 22 23 toast_loc = ("xpath", ".//*[contains(@text,'%s')]"%text) 24 25
WebDriverWait(driver, timeout,
poll_frequency).until(EC.presence_of_element_located(toast_loc))26 27 return
True28 29 except: 30 31 return False
封装后参考代码
1 # coding=utf-8 2 # 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行 3 4 # 2
.注释:包括记录创建时间,创建人,项目名称。 5 ''' 6 Created on 2019-7-31 7 @author: 北京-宏哥 QQ交流群:
707699217 8 Project:学习和使用appium自动化测试-toast提示 9 ''' 10 # 3.导入模块 11 from appium
import webdriver12 from selenium.common.exceptions import NoSuchElementException
13 from selenium.webdriver.support.ui import WebDriverWait 14 from
selenium.webdriver.support import expected_conditionsas EC 15 16 desired_caps =
{'platformName': 'Android', 17 'platforVersion': '5.1.1', 18 'automationName': '
Uiautomator2', 19 'deviceName': '127.0.0.1:62001', 20 'app': r'
C:\Users\DELL\Downloads\kaoyanbang.apk', 21 'appPackage': 'com.tal.kaoyan', 22 '
appActivity': 'com.tal.kaoyan.ui.activity.SplashActivity', 23 'noReset': 'True'}
24 25 def is_toast_exist(driver,text,timeout=30,poll_frequency=0.5): 26 27 '''
is toast exist, return True or False 28 29 :Agrs: 30 31 - driver - 传driver 32
33 - text - 页面上看到的文本内容 34 35 - timeout - 最大超时时间,默认30s 36 37 - poll_frequency -
间隔查询时间,默认0.5s查询一次38 39 :Usage: 40 41 is_toast_exist(driver, "看到的内容") 42 43 '''
44 45 try: 46 47 toast_loc = ("xpath", ".//*[contains(@text,'%s')]"%text) 48 49
WebDriverWait(driver, timeout,
poll_frequency).until(EC.presence_of_element_located(toast_loc))50 51 return
True52 53 except: 54 55 return False 56 if __name__ == "__main__": 57 58
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) 59
driver.implicitly_wait(9) 60 try: 61 driver.find_element_by_id("
android:id/button2").click() 62 except NoSuchElementException: 63 print(1) 64
try: 65 driver.find_element_by_id('com.tal.kaoyan:id/tv_skip').click() 66
except NoSuchElementException:67 print(2) 68 driver.find_element_by_id('
com.tal.kaoyan:id/login_email_edittext').clear() 69 driver.find_element_by_id('
com.tal.kaoyan:id/login_email_edittext').send_keys('bjhongge') 70 71
driver.find_element_by_id('com.tal.kaoyan:id/login_password_edittext'
).send_keys('1213213') 72 driver.find_element_by_id('
com.tal.kaoyan:id/login_login_btn').click() 73 74 error_message = "
用户名或密码错误,你还可以尝试3次" 75 limit_message = "验证失败次数过多,请15分钟后再试" 76 77 print
is_toast_exist(driver, error_message)
 小结

1.注意:Toast内容为中文时,顶部必须注释# coding=utf-8 否则会因为编解码导致文字识别失败。

2. 用npm安装appium-uiautomator2-driver ,会出现错误,卡顿之后安装不成功。



解决办法

(1)首先执行这个命令:npm install -g cnpm --registry=https://registry.npm.taobao.org
       安装cnpm(完成后如下图)





(2)然后通过这个命令: cnpm install appium-uiautomator2-driver   安装uiautomator2的配置文件,如图



3.cnpm与npm的区别:

(1)npm介绍

说明:npm(node package manager)是nodejs的包管理器,用于node插件管理(包括安装、卸载、管理依赖等) 
(2)使用npm安装插件:命令提示符执行npm install [-g] [–save-dev] 
:node插件名称。 
例:npm install gulp-less –save-dev 
-g:全局安装。 
将会安装在C:\Users\Administrator\AppData\Roaming\npm,并且写入系统环境变量; 非全局安装:将会安装在当前定位目录;
全局安装可以通过命令行在任何地方调用它,本地安装将安装在定位目录的node_modules文件夹下,通过require()调用;

–save:将保存配置信息至package.json(package.json是nodejs项目配置文件);

-dev:保存至package.json的devDependencies节点,不指定-dev将保存至dependencies节点;


为什么要保存至package.json?因为node插件包相对来说非常庞大,所以不加入版本管理,将配置信息写入package.json并将其加入版本管理,其他开发者对应下载即可(命令提示符执行npm
install,则会根据package.json下载所有需要的包)。 
(3)使用npm卸载插件:npm uninstall [-g] [–save-dev] 
PS:不要直接删除本地插件包 
(4)使用npm更新插件:npm update [-g] [–save-dev] 
(5)更新全部插件:npm update [–save-dev] 
(6)查看npm帮助:npm help 
(7)查看当前目录已安装插件:npm list

PS:npm安装插件过程:从http://registry.npmjs.org下载对应的插件包(该网站服务器位于国外,所以经常下载缓慢或出现异常),

解决办法:

选装cnpm


说明:因为npm安装插件是从国外服务器下载,受网络影响大,可能出现异常,如果npm的服务器在中国就好了,所以我们乐于分享的淘宝团队干了这事。来自官网:“这是一个完整
npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。” 
官方网址:http://npm.taobao.org 
安装:命令提示符执行npm install cnpm -g –registry=https://registry.npm.taobao.org 
注意:安装完后最好查看其版本号cnpm -v或关闭命令提示符重新打开,安装完直接使用有可能会出现错误 
注:cnpm跟npm用法完全一致,只是在执行命令时将npm改为cnpm。

4.好了,时间不早了!至此,有关toast的提示,就给小伙伴们和童鞋们方向到这里,谢谢你耐心的阅读!

您的肯定就是我进步的动力。如果你感觉还不错,就请鼓励一下吧!记得点波 推荐 哦!!!(点击右边的小球即可,胆子大的可以试一下哦! :))


       个人公众号                                                             微信群