完成app自動(dòng)化需要一些基礎(chǔ)條件的支持,本節(jié)將講解APP初始化API.
3.1.1前置代碼
server 啟動(dòng)參數(shù)
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
desired_caps['unicodeKeyboard'] = True
desired_caps['resetKeyboard'] = True
聲明driver對(duì)象
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
3.1.2安裝APK到手機(jī)
driver.install_app(app_path)
參數(shù):
app_path:腳本機(jī)器中APK文件路徑
3.1.3手機(jī)中移除APP
driver.remove_app(app_id)
參數(shù):
app_id:需要卸載的app包名
3.1.4判斷APP是否已安裝
driver.is_app_installed(bundle_id)
參數(shù):
bundle_id: 可以傳入app包名,返回結(jié)果為True(已安裝) / False(未安裝)
3.1.5發(fā)送文件到手機(jī)
import base64
data = str(base64.b64encode(data.encode('utf-8')),'utf-8')
driver.push_file(path,data)
參數(shù):
path:手機(jī)設(shè)備上的路徑(例如:/sdcard/a.txt)
data:文件內(nèi)數(shù)據(jù),要求base64編碼
Python3.x中字符都為unicode編碼,而b64encode函數(shù)的參數(shù)為byte類型,需要先轉(zhuǎn)碼;
生成的數(shù)據(jù)為byte類型,需要將byte轉(zhuǎn)換回去。
3.1.6從手機(jī)中拉取文件
import base64
data = driver.pull_file(path) # 返回?cái)?shù)據(jù)為base64編碼
print(str(base64.b64decode(data),'utf-8')) # base64解碼
參數(shù):
path: 手機(jī)設(shè)備上的路徑
3.1.7獲取當(dāng)前屏幕內(nèi)元素結(jié)構(gòu)
driver.page_source
作用:
返回當(dāng)前頁(yè)面的文檔結(jié)構(gòu),判斷特定的元素是否存在
手機(jī)控件查看工具uiautomatorviewer
-
工具簡(jiǎn)介
用來(lái)掃描和分析Android應(yīng)用程序的UI控件的工具. 如何使用
1.進(jìn)入SDK目錄下的tools目錄,打開uiautomatorviewer
2.電腦連接真機(jī)或打開android模擬器
3.啟動(dòng)待測(cè)試app
4.點(diǎn)擊uiautomatorviewer的左上角Device Screenshot,會(huì)生成app當(dāng)前頁(yè)面的UI控件截圖
我是在bin目錄下

5.選擇截圖上需要查看的控件,即可瀏覽該控件的id,class,text,坐標(biāo)等信息

.APP元素定位操作
手工測(cè)試主要通過(guò)可見按鈕操作,而自動(dòng)化是通過(guò)元素進(jìn)行交互操作.
?????? 元素的基本定位基于當(dāng)前屏幕范圍內(nèi)展示的可見元素。
3.3.1Appium常用元素定位方式
name value
id id屬性值
class class屬性值
xpath xpath表達(dá)式
3.3.2.前置代碼
from appium import webdriver
# server 啟動(dòng)參數(shù)
desired_caps = {}
# 設(shè)備信息
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
# app的信息
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
# 聲明我們的driver對(duì)象
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
3.3.3.通過(guò)id定位
方法:find_element_by_id(id_value) # id_value:為元素的id屬性值
業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置頁(yè)面
2.通過(guò)ID定位方式點(diǎn)擊搜索按鈕
代碼實(shí)現(xiàn):
driver.find_element_by_id("com.android.settings:id/search").click()
driver.quit()
3.3.4.通過(guò)class定位
方法:find_element_by_class_name(class_value) # class_value:為元素的class屬性值
業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置頁(yè)面
2.點(diǎn)擊搜索按鈕
3.通過(guò)class定位方式點(diǎn)擊輸入框的返回按鈕
代碼實(shí)現(xiàn):
# id 點(diǎn)擊搜索按鈕
driver.find_element_by_id("com.android.settings:id/search").click()
# class 點(diǎn)擊輸入框返回按鈕
driver.find_element_by_class_name('android.widget.ImageButton').click()
driver.quit()
3.3.5.通過(guò)xpath定位
方法:find_element_by_xpath(xpath_value) # xpath_value:為可以定位到元素的xpath語(yǔ)句
*** android端xptah常用屬性定位:
1. id ://[contains(@resource-id,'com.android.settings:id/search')]
2. class ://[contains(@class,'android.widget.ImageButton')]
3. text ://*[contains(@text,'WLA')]
*** 模糊定位 contains(@key,value): value可以是部分值
業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置頁(yè)面
2.點(diǎn)擊WLAN菜單欄
代碼實(shí)現(xiàn):
# xpath 點(diǎn)擊WLAN按鈕
driver.find_element_by_xpath("http://[contains(@text,'WLA')]").click()
3.3.6.定位一組元素,注意element -> elements
應(yīng)用場(chǎng)景為元素值重復(fù),無(wú)法通過(guò)元素屬性直接定位到某個(gè)元素,只能通過(guò)elements方式來(lái)選擇,返回一個(gè)定位對(duì)象的列表.
3.3.7.通過(guò)id方式定位一組元素
方法: find_elements_by_id(id_value) # id_value:為元素的id屬性值
業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置頁(yè)面
2.點(diǎn)擊WLAN菜單欄(id定位對(duì)象列表中第1個(gè))
代碼實(shí)現(xiàn):
# 定位到一組元素
title = driver.find_elements_by_id("com.android.settings:id/title")
# 打印title類型,預(yù)期為list
print(type(title))
# 取title返回列表中的第一個(gè)定位對(duì)象,執(zhí)行點(diǎn)擊操作
title[0].click()
3.3.8.通過(guò)class方式定位一組元素
方法:find_elements_by_class_name(class_value) # class_value:為元素的class屬性值
業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置頁(yè)面
2.點(diǎn)擊WLAN菜單欄(class定位對(duì)象列表中第3個(gè))
代碼實(shí)現(xiàn):
# 定位到一組元素
title = driver.find_elements_by_class_name("android.widget.TextView")
# 打印title類型,預(yù)期為list
print(type(title))
# 取title返回列表中的第一個(gè)定位對(duì)象,執(zhí)行點(diǎn)擊操作
title[3].click()
3.3.9.通過(guò)xpath方式定位一組元素
方法:find_elements_by_xpath(xpath_value) # xpath_value:為可以定位到元素的xpath語(yǔ)句
業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置頁(yè)面
2.點(diǎn)擊WLAN菜單欄(xpath中class屬性定位對(duì)象列表中第3個(gè))
代碼實(shí)現(xiàn):
# 定位到一組元素
title = driver.find_elements_by_xpath("http://[contains(@class,'widget.TextView')]")
# 打印title類型,預(yù)期為list
print(type(title))
# 取title返回列表中的第一個(gè)定位對(duì)象,執(zhí)行點(diǎn)擊操作
title[3].click()
WebDriverWait 顯示等待操作
在一個(gè)超時(shí)時(shí)間范圍內(nèi),每隔一段時(shí)間去搜索一次元素是否存在,
如果存在返回定位對(duì)象,如果不存在直到超時(shí)時(shí)間到達(dá),報(bào)超時(shí)異常錯(cuò)誤。
方法:WebDriverWait(driver, timeout, poll_frequency).until(method)
參數(shù):
1.driver:手機(jī)驅(qū)動(dòng)對(duì)象
2.timeout:搜索超時(shí)時(shí)間
3.poll_frequency:每次搜索間隔時(shí)間,默認(rèn)時(shí)間為0.5s
4.method:定位方法(匿名函數(shù))
匿名函數(shù):
lambda x: x
等價(jià)于python函數(shù):
def test(x):
return x
使用示例:
WebDriverWait(driver, timeout, poll_frequency).until(lambda x: x.find_elements_by_id(id_value))
解釋:
1.x傳入值為:driver,所以才可以使用定位方法.
函數(shù)運(yùn)行過(guò)程:
1.實(shí)例化WebDriverWait類,傳入driver對(duì)象,之后driver對(duì)象被賦值給WebDriverWait的一個(gè)類變量:self._driver
2.until為WebDriverWait類的方法,until傳入method方法(即匿名函數(shù)),之后method方法會(huì)被傳入self._driver
3.搜索到元素后until返回定位對(duì)象,沒有搜索到函數(shù)until返回超時(shí)異常錯(cuò)誤.
業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置頁(yè)面
2.通過(guò)ID定位方式點(diǎn)擊搜索按鈕
代碼實(shí)現(xiàn):
from selenium.webdriver.support.wait import WebDriverWait # 導(dǎo)入WebDriverWait類
# 超時(shí)時(shí)間為30s,每隔1秒搜索一次元素是否存在,如果元素存在返回定位對(duì)象并退出
search_button = WebDriverWait(driver, 30, 1).until(lambda driver: driver.find_element_by_id("com.android.settings:id/search"))
search_button.click()
driver.quit()