Appium上下文和H5測試(二)

堅持原創輸出,點擊藍字關注我吧

做者:清菡
博客:oschina、雲+社區、知乎等各大平臺都有。html

文章總覽圖

1、往期回顧

loc='new UiSelector().text("全程班")'
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.ANDROID_UIAUTOMATOR,loc))
driver.find_element_by_android_uiautomator(loc).click()

這個步驟後進入了這個頁面:android

進入這個頁面也是須要時間的。WebView 這個元素當中,放的纔是 html 頁面。真的等到 html 頁面加載出來以後,再去獲取全部相關的內容,這樣比較好。web

萬一切過來的時候,html 頁面尚未開始加載,我就立刻去獲取當前全部能夠操做的對象,這樣很容易丟失,因此也同樣要講究等待。chrome

講究等待,首先等到 WebView 這個元素出現。等到 WebView 這個 class 控件出現,class 值表明它的控件。session

# 等待Web View元素出現  -Web View裏面放的是Html
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.CLASS_NAME,'android.webkit.WebView')))

sleep1 秒鐘,確保裏面的 html,全部的都能加載完成。app

time.sleep(1)koa

2、怎麼切換?

用什麼樣的語句來獲取咱們的 WebView、獲取咱們的原生控件呢?

它這個東西在咱們 App 當中叫作context,翻譯成中文就是上下文。編輯器

上下文在咱們自動化中就是指能夠切換的東西,就是咱們的原生控件。 原生控件是咱們默認的,就像窗口切換就是咱們默認的窗口是同樣的。原生控件是它的默認上下文。打開 app,默認就是在它的原生控件當中。佈局

WebView 就是它的第二種context測試

只要當前頁面中有 WebView,它就會顯示出來,有 2 個就會顯示 2 個。如圖片中這個例子中只有一個 Webview,因此它只顯示一個 WebView。

這就是context上下文。

只有這種狀況下須要切換,其它狀況下都是原生控件就不須要切換,不用管它,一旦有 html 頁面就須要考慮這些事情了。

3、上下文切換

可用的上下文(Contexts)

列出全部可用的上下文(contexts)

driver.contexts

driver.window_handles 獲取全部窗口的 handle,返回 list 列表。

當前上下文(context):列出當前的上下文(context)

driver.current_context

切換至默認的上下文(context)

切換回默認的上下文(context)。(譯者注:通常就是原生上下文 「NATIVE_APP」)

driver.switch_to.context(None)

當前 Activity:獲取當前的 Acticity。僅支持 Android。

driver.current_activity

當前包名(package):獲取當前包名(package)。僅支持 Android 。

driver.current_package

上下文的操做方式在這裏,和 Windows 窗口是如出一轍的。和 Web 自動化中所謂的窗口是同樣的。

首先列出全部可用的上下文。就像列出目前全部打開的窗口是同樣的。

這個上下文,有 WebView 的時候,也是在執行代碼的時候,它進入了有 WebView 的頁面當中,纔會有多個,沒有進入有 WebView 的頁面當中只有一個 WebView 的(至關於一個大箱子,箱子打開後有多個)。

列出全部可用的上下文,再去切換至須要的上下文。怎麼切換呢?他們獲得的結果也是個列表啊。

列表當中放的值呢,不是原生控件就是 WebView。因此它也有下標。若是要切換的話就是driver.switch_to.context(None)

None 表示什麼呢?

表示切換回默認的上下文,按照 Web 自動化的講法就是默認的窗口,在咱們這裏就是默認的原生控件裏面。

若是你想切換到 WebView 的話,driver.contexts返回值 0,列表取下標 1,2,3,4 都是能夠取得。也能夠將你獲得的 Web 名稱放在driver.switch_to.context(None)中替換 None 就能夠了。

driver.switch_to.context(None)能夠切進去,也能夠切出來。若是你想獲取當前的窗口,當前的上下文,叫作driver.current_context

它的作法與窗口是如出一轍的。Web 自動化中叫作窗口,這裏叫作上下文。 其它的時候不須要切換,可是有窗口須要交替的時候就必需要切換。有 iframe,須要更換 html 頁面的時候就須要切換,其它狀況下就不切換。

如今在這個地方已經等到了這個全部的 WebView 出現了,因此接下來這樣作:

button[@class="bottom-btn buy"]

至關於 App 自動化和 Web 自動化組合起來用了,無縫切換,不須要改什麼,照着套路用就行了:

# 切換以後:當前的操做對象:html頁面。
# 等待元素可見
# 由於是通用的,因此接下來的代碼是web自動化的代碼
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.XPATH,'//button[@class="bottom-btn buy"]')))
# 這個用Mobileby或者By都無所謂。
driver.find_element_by_xpath('//button[@class="bottom-btn buy"]').click()

列出了當前的上下文:

['NATIVE_APP', 'WEBVIEW_com.tencent.mobileqq:mini', 'WEBVIEW_com.保密']

NATIVE_APP 是當前的原生控件,按照 web 自動化來講,是默認的主窗口。

是由於這段代碼:

# 一、先列出全部的context
cons=driver.contexts  #列表
#也是按照出現的前後順序,WebView是操做過程當中纔出現的,因此它確定排隊。
print(cons)

必定要開啓 webview debug 屬性,若是你沒有開啓它,那麼這 2 項,在這裏獲取的時候是看不到的:

就只有一個了,就是 NATIVE_APP。只能看到 NATIVE_APP 是切換不到 WebView 的。必定要保證可以識別獲得,纔可以去切換。

技巧: 報錯的時候先看第一行代碼,看看在你本身當前腳本當中究竟是哪一行出錯了。

4、樣例代碼

手機設置中開啓着顯示佈局邊界的狀況下,而後 run 代碼。由於 App 界面有變動,因此代碼和現有界面不一致,即當即購買如今成了報名截止並跳轉至 QQ 界面。代碼提示找不到元素請不要奇怪,由於爲了便於理解,放的元素仍是當即購買的元素。

此代碼只是樣例,不必定保證在你的電腦上就能運行成功,請根據實際狀況修改。

from appium import webdriver
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium.webdriver.common.mobileby import MobileBy


desired_caps={}
# 平臺類型
desired_caps["platformName"]="Android"
# 平臺版本號
desired_caps["platformVersion"]="10"
# 設備名稱
desired_caps["deviceName"]="2NSDU20410017297"
# app 包名
desired_caps["appPackage"]="輸入appPackage"
# app 入口 acitivity
desired_caps["appActivity"]="輸入appActivity"


# 鏈接Appium server。前提:appium desktop要啓動。有監聽端口。
# 將desired_caps發送給appium server。打開app
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)

loc='new UiSelector().text("全程班")'
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.ANDROID_UIAUTOMATOR,loc)))
driver.find_element_by_android_uiautomator(loc).click()



# 等待Web View元素出現  -Web View裏面放的是Html
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.CLASS_NAME,'android.webkit.WebView')))
# 由於只是等它這個元素出現了,至於裏面的html有沒有加載完成,並非很肯定。
time.sleep(1)#爲了穩定起見,稍微sleep 1秒,確保裏面的Html,全部的都能加載完成。

# 前提:能夠識別到WebView,
# 這個識別不是肉眼識別,而是經過調用代碼的時候能夠識別。須要開啓app的webview debug調試屬性,對外可見。

# context  #原生控件 #webview

# 一、先列出全部的context
cons=driver.contexts  #列表
#也是按照出現的前後順序,WebView是操做過程當中纔出現的,因此它確定排隊。
print(cons)

# 二、切換至WebView,要確保chromedriver的版本要與webView的版本匹配。也要放置在對應的位置。
driver.switch_to.context(cons[-1])#這個地方沒有給你提示,不表明你錯了,照着操做就行了。
# 先寫個-1,由於如今不知道WebView的名字。可是知道WebView必定是出如今最後的就能夠了。

# 三、切換以後:當前的操做對象:html頁面。
# 等待元素可見
# 由於是通用的,因此接下來的代碼是web自動化的代碼
WebDriverWait(driver,20).until(EC.visibility_of_element_located((MobileBy.XPATH,'//button[@class="bottom-btn buy"]')))
# 這個用Mobileby或者By都無所謂。
driver.find_element_by_xpath('//button[@class="bottom-btn buy"]').click()
# 這裏爲何用MobileBy.XPATH而不是By.XPATH?
# MobileBy這個類繼承了By,因此這個用Mobileby或者By都無所謂。
# 原理:你們背後走的都是同一套邏輯,同一段請求,同一種命令。都是find_element
# 只不過咱們查找元素的方式不同。因此它只是一個外部的形式而已,在內部也是同樣的。
# 即使用Selenium Webdriver 寫代碼,也能夠把MobileBy引進來,只要我不去用移動端的定位方式,都是能夠作的。

遇到的問題

appium 報錯 session not created: This version of ChromeDriver only supports Chrome version 84

靠譜連接: https://www.codenong.com/jsb8d9e8746809/

舒適提示: 若是你的代碼沒問題,還報錯,那麼就換 Appium 版本吧,Appium 的 bug 不少。

上篇文章 中此處代碼錯了,應該改爲這樣:


公衆號 清菡軟件測試 首發,更多原創文章:清菡軟件測試 95+原創文章,歡迎關注、交流,禁止第三方擅自轉載。

相關文章
相關標籤/搜索