在日常使用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看到對應的文件:
_appium-uiautomator2-driver@1.12.0@appium-uiautomator2-driver
_appium-uiautomator2-server@1.10.0@appium-uiautomator2-server
測試環境
1.系統環境是Windows 10版本 64位系統
2.jdk版本:"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. 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 appium@xxx,xxx是版本號,如下載appium1.6.3,命令為npm install -g appium@1.7.0,我是一開始使用方法一,之后發現幾個功能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()連接路徑和文本內容
參考代碼
11 from appium import webdriver
12 from selenium.common.exceptions import NoSuchElementException
13 from selenium.webdriver.support.ui import WebDriverWait
14 from selenium.webdriver.support import expected_conditions as 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 False4 5 :Agrs:6 7 - driver - 傳driver8 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 True
28
29 except:
30
31 return False
封裝后參考代碼
11 from appium import webdriver
12 from selenium.common.exceptions import NoSuchElementException
13 from selenium.webdriver.support.ui import WebDriverWait
14 from selenium.webdriver.support import expected_conditions as 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 True
52
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 listPS: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。