第三十五 APP移動(dòng)端測(cè)試高級(jí)

一、Appium介紹

Appium是一個(gè)移動(dòng)端的自動(dòng)化框架,可用于測(cè)試原生應(yīng)用、移動(dòng)網(wǎng)頁(yè)應(yīng)用和混合型應(yīng)用,且是跨平臺(tái)的??捎糜贗OS和Android以及firefox的操作系統(tǒng)。

原生的應(yīng)用是指用android或ios的sdk編寫(xiě)的應(yīng)用;移動(dòng)網(wǎng)頁(yè)應(yīng)用是指網(wǎng)頁(yè)應(yīng)用,類(lèi)似于ios中safari應(yīng)用或者Chrome應(yīng)用或者類(lèi)瀏覽器的應(yīng)用;混合應(yīng)用是指一種包裹webview的應(yīng)用,原生應(yīng)用于網(wǎng)頁(yè)內(nèi)容交互性的應(yīng)用。

重要的是Appium是跨平臺(tái)的,何為跨平臺(tái),意思就是可以針對(duì)不同的平臺(tái)用一套api來(lái)編寫(xiě)測(cè)試用例。

二、環(huán)境搭建

主要幾個(gè)點(diǎn)如下:

image

1. appium安裝

直接解壓即可,打開(kāi)Appium.exe

image

啟動(dòng)成功展示如下:

image

2. Appium庫(kù)安裝

# 安裝
pip install Appium-Python-Client
# 檢驗(yàn)是否成功
pip list

三、Appium使用

1. 打開(kāi)模擬器或真機(jī)的應(yīng)用

①打開(kāi)手機(jī)應(yīng)用
②打開(kāi)Appium
③創(chuàng)建一個(gè)python項(xiàng)目,并創(chuàng)建一個(gè)文件
④將下面代碼復(fù)制到文件中
⑤獲取當(dāng)前應(yīng)用包名和啟動(dòng)activity并修改文件

from appium import webdriver
# server 啟動(dòng)參數(shù)
desired_caps = dict()
# 設(shè)備信息
# 平臺(tái)信息,不區(qū)分大小寫(xiě)
desired_caps['platformName'] = 'Android'
# 系統(tǒng)版本,7.1.2可以寫(xiě)[7 ,7.1 , 7.1.2]
desired_caps['platformVersion'] = '7.1.2'
# 設(shè)備名稱,可以隨便寫(xiě),但是不能亂寫(xiě),Android可以隨便寫(xiě),但是ios必須正確的寫(xiě)
desired_caps['deviceName'] = 'emulator-5554'
# 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)
driver.quit()

2. 腳本內(nèi)啟動(dòng)其他app

driver.start_activity(appPackage,appActivity)

3. 關(guān)閉app

driver.close_app()  # 關(guān)閉當(dāng)前操作的app,不會(huì)關(guān)閉驅(qū)動(dòng)對(duì)象

4. 關(guān)閉驅(qū)動(dòng)對(duì)象

driver.quit()   # 關(guān)閉驅(qū)動(dòng)對(duì)象,同時(shí)關(guān)閉所有關(guān)聯(lián)的app

三、App基礎(chǔ)操作API

完成app自動(dòng)化需要一些基礎(chǔ)條件的支持,本節(jié)將講解APP初始化API。

3.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.2 安裝APK到手機(jī)

driver.install_app(app_path) 

參數(shù):app_path:腳本機(jī)器中APK文件路徑

3.3 手機(jī)中移除APP

driver.remove_app(app_id) 

參數(shù):app_id:需要卸載的app包名

3.4 判斷APP是否已安裝

driver.is_app_installed(bundle_id) 

參數(shù):bundle_id: 可以傳入app包名,返回結(jié)果為T(mén)rue(已安裝) / False(未安裝)
3.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類(lèi)型,需要先轉(zhuǎn)碼;
生成的數(shù)據(jù)為byte類(lèi)型,需要將byte轉(zhuǎn)換回去。

3.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.7獲取當(dāng)前屏幕內(nèi)元素結(jié)構(gòu)

driver.page_source  

作用:返回當(dāng)前頁(yè)面的文檔結(jié)構(gòu),判斷特定的元素是否存在

四、手機(jī)控件查看工具uiautomatorviewer

4.1 工具簡(jiǎn)介

用來(lái)掃描和分析Android應(yīng)用程序的UI控件的工具.

4.1 如何使用

  1. 進(jìn)入SDK目錄下的tools目錄,打開(kāi)uiautomatorviewer

  2. 電腦連接真機(jī)或打開(kāi)android模擬器

  3. 啟動(dòng)待測(cè)試app

  4. 點(diǎn)擊uiautomatorviewer的左上角Device Screenshot,會(huì)生成app當(dāng)前頁(yè)面的UI控件截圖

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

    image

五、APP元素定位操作

手工測(cè)試主要通過(guò)可見(jiàn)按鈕操作,而自動(dòng)化是通過(guò)元素進(jìn)行交互操作。
元素的基本定位基于當(dāng)前屏幕范圍內(nèi)展示的可見(jiàn)元素。

5.1 Appium常用元素定位方式

name value
id id屬性值
class class屬性值
xpath xpath表達(dá)式

5.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)

5.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()
    
    

5.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()

5.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()
    
    

5.6 定位一組元素,注意element -> elements

應(yīng)用場(chǎng)景為元素值重復(fù),無(wú)法通過(guò)元素屬性直接定位到某個(gè)元素,只能通過(guò)elements方式來(lái)選擇,返回一個(gè)定位對(duì)象的列表.

5.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類(lèi)型,預(yù)期為list
    print(type(title))
    # 取title返回列表中的第一個(gè)定位對(duì)象,執(zhí)行點(diǎn)擊操作
    title[0].click()
    

5.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類(lèi)型,預(yù)期為list

print(type(title))

取title返回列表中的第一個(gè)定位對(duì)象,執(zhí)行點(diǎn)擊操作

title[3].click()
for index, item in enumerate(ele_list):
print(index, item.text) ```
5.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類(lèi)型,預(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))
解釋?zhuān)?br> 1.x傳入值為:driver,所以才可以使用定位方法。
函數(shù)運(yùn)行過(guò)程:
1.實(shí)例化WebDriverWait類(lèi),傳入driver對(duì)象,之后driver對(duì)象被賦值給WebDriverWait的一個(gè)類(lèi)變量:self._driver
2.until為WebDriverWait類(lèi)的方法,until傳入method方法(即匿名函數(shù)),之后method方法會(huì)被傳入self._driver
3.搜索到元素后until返回定位對(duì)象,沒(méi)有搜索到函數(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 類(lèi)

超時(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()
七、APP元素信息操作API
本節(jié)講介紹手機(jī)端元素信息的獲取以及基本的輸入操作。

7.1. 點(diǎn)擊元素
ele.click()
7.2.發(fā)送數(shù)據(jù)到輸入框
方法:send_keys(vaue) # value:需要發(fā)送到輸入框內(nèi)的文本

業(yè)務(wù)場(chǎng)景:
1.打開(kāi)設(shè)置
2.點(diǎn)擊搜索按鈕
3.輸入內(nèi)容abc

代碼實(shí)現(xiàn):

點(diǎn)擊搜索按鈕

driver.find_element_by_id("com.android.settings:id/search").click()

定位到輸入框并輸入abc

driver.find_element_by_id("android:id/search_src_text").send_keys("abc")
重點(diǎn):大家可以將輸入的abc 改成 輸入中文,得到的結(jié)果:輸入框無(wú)任何值輸入且程序不會(huì)抱錯(cuò)
解決輸入中文問(wèn)題:

1.server 啟動(dòng)參數(shù)增加兩個(gè)參數(shù)配置
desired_caps['unicodeKeyboard'] = True
desired_caps['resetKeyboard'] = True

2.再次運(yùn)行會(huì)發(fā)現(xiàn)運(yùn)行成功
# 點(diǎn)擊搜索按鈕
driver.find_element_by_id("com.android.settings:id/search").click()
# 定位到輸入框并輸入abc
driver.find_element_by_id("android:id/search_src_text").send_keys("積云教育")
7.3. 清空輸入框內(nèi)容
方法:clear()
業(yè)務(wù)場(chǎng)景:
1.打開(kāi)設(shè)置
2.點(diǎn)擊搜索按鈕
3.輸入內(nèi)容abc
4.刪除已輸入abc
代碼實(shí)現(xiàn):

點(diǎn)擊搜索按鈕

driver.find_element_by_id("com.android.settings:id/search").click()

定位到輸入框并輸入abc

input_text = driver.find_element_by_id("android:id/search_src_text")

輸入abc

input_text.send_keys("abc")
time.sleep(1)

刪除abc

input_text.clear()
7.4. 獲取元素的文本內(nèi)容
方法: text
業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置
2.獲取所有元素class屬性為“android.widget.TextView”的文本內(nèi)容
代碼實(shí)現(xiàn):
ele_list = driver.find_elements_by_class_name("android.widget.TextView")
for e in ele_list:
print(e.text)
for index, item in enumerate(ele_list):
print(index, item.text)
執(zhí)行結(jié)果:
0 設(shè)置
1
2 移動(dòng)數(shù)據(jù)網(wǎng)絡(luò)已關(guān)閉
3 無(wú)線和網(wǎng)絡(luò)
4 WLAN
5 "guest"
6 藍(lán)牙
7 已停用
8 流量使用情況
9 已使用 0 B 的數(shù)據(jù)
10 更多
11 設(shè)備
12 顯示
13 自動(dòng)調(diào)節(jié)亮度功能已關(guān)閉
14 通知
15 已允許所有應(yīng)用發(fā)送通知
7.5. 獲取元素的屬性值
方法: get_attribute(value) # value:元素的屬性
?? value='name' 返回content-desc / text屬性值
?? value='text' 返回text的屬性值
?? value='className' 返回 class屬性值,只有 API=>18 才能支持
?? value='resourceId' 返回 resource-id屬性值,只有 API=>18 才能支持

業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置
2.獲取搜索按鈕的content-desc屬性值

代碼實(shí)現(xiàn):

定位到搜索按鈕

get_value = driver.find_element_by_id("com.android.settings:id/search")
print(get_value.get_attribute("content-desc"))
執(zhí)行結(jié)果:
搜索
7.6. 獲取元素在屏幕上的坐標(biāo)
方法:location
業(yè)務(wù)場(chǎng)景:
1.進(jìn)入設(shè)置頁(yè)面
2.獲取搜索按鈕在屏幕的坐標(biāo)位置
代碼實(shí)現(xiàn):

定位到搜索按鈕

get_value = driver.find_element_by_id("com.android.settings:id/search")

打印搜索按鈕在屏幕上的坐標(biāo)

print(get_value.location)
{'y': 44, 'x': 408}
7.7. 獲取app包名和啟動(dòng)名
獲取包名方法:current_package
獲取啟動(dòng)名:current_activity
業(yè)務(wù)場(chǎng)景:
1.啟動(dòng)設(shè)置
2.獲取包名和啟動(dòng)名
代碼實(shí)現(xiàn):
print(driver.current_package)
print(driver.current_activity)
執(zhí)行結(jié)果:

com.tencent.news
.activity.SplashActivity

八、APP元素事件操作API

8.1. 前置代碼

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)

8.2. swip滑動(dòng)事件

??從一個(gè)坐標(biāo)位置滑動(dòng)到另一個(gè)坐標(biāo)位置,只能是兩個(gè)點(diǎn)之間的滑動(dòng)

  • 方法:swipe(start_x, start_y, end_x, end_y, duration=None)

  • 參數(shù):
    1.start_x:起點(diǎn)X軸坐標(biāo)
    2.start_y:起點(diǎn)Y軸坐標(biāo)
    3.end_x: 終點(diǎn)X軸坐標(biāo)
    4.end_y,: 終點(diǎn)Y軸坐標(biāo)
    5.duration: 滑動(dòng)這個(gè)操作一共持續(xù)的時(shí)間長(zhǎng)度,單位:ms

    • 業(yè)務(wù)場(chǎng)景:
      1.進(jìn)入設(shè)置
      2.從坐標(biāo)(148,659)滑動(dòng)到坐標(biāo)(148,248)
  • 代碼實(shí)現(xiàn):

    # 滑動(dòng)沒(méi)有持續(xù)時(shí)間
    driver.swipe(188,659,148,248)
    # 滑動(dòng)持續(xù)5秒的時(shí)間
    driver.swipe(188,659,148,248,5000)
    
    

8.3. scroll滑動(dòng)事件

?? 從一個(gè)元素滑動(dòng)到另一個(gè)元素,直到頁(yè)面自動(dòng)停止

  • 方法:scroll(origin_el, destination_el)

  • 參數(shù):
    1.origin_el:滑動(dòng)開(kāi)始的元素
    2.destination_el:滑動(dòng)結(jié)束的元素

  • 業(yè)務(wù)場(chǎng)景:
    1.進(jìn)入設(shè)置頁(yè)
    2.模擬手指從存儲(chǔ)菜單位置 到 WLAN菜單位置的上滑操作

  • 代碼實(shí)現(xiàn):

    # 定位到存儲(chǔ)菜單欄
    el1 = driver.find_element_by_xpath("http://*[contains(@text,'存儲(chǔ)')]")
    # 定位到WLAN菜單欄
    el2 = driver.find_element_by_xpath("http://*[contains(@text,'WLAN')]")
    # 執(zhí)行滑動(dòng)操作
    driver.scroll(el1,el2)
    
    

8.4. drag拖拽事件

?? 從一個(gè)元素滑動(dòng)到另一個(gè)元素,第二個(gè)元素替代第一個(gè)元素原本屏幕上的位置

  • 方法:drag_and_drop(origin_el, destination_el)

  • 參數(shù):
    1.origin_el:滑動(dòng)開(kāi)始的元素
    2.destination_el:滑動(dòng)結(jié)束的元素

  • 業(yè)務(wù)場(chǎng)景:
    1.進(jìn)入設(shè)置頁(yè)
    2.模擬手指將存儲(chǔ)菜單 滑動(dòng)到 WLAN菜單欄位置

  • 代碼實(shí)現(xiàn):

    # 定位到存儲(chǔ)菜單欄
    el1 = driver.find_element_by_xpath("http://*[contains(@text,'存儲(chǔ)')]")
    # 定位到WLAN菜單欄
    el2 = driver.find_element_by_xpath("http://*[contains(@text,'WLAN')]")
    # 執(zhí)行滑動(dòng)操作
    driver.drag_and_drop(el1,el2)
    
    

8.5. 應(yīng)用置于后臺(tái)事件

APP放置后臺(tái),模擬熱啟動(dòng)

  • 方法:background_app(seconds)

  • 參數(shù):
    1.seconds:停留在后臺(tái)的時(shí)間,單位:秒

  • 業(yè)務(wù)場(chǎng)景:
    1.進(jìn)入設(shè)置頁(yè)
    2.將APP置于后臺(tái)5s

  • 代碼實(shí)現(xiàn):

    driver.background_app(5)
    
    
  • 效果:

    app置于后臺(tái)5s后,再次展示當(dāng)前頁(yè)面
    
    

九、APP模擬手勢(shì)高級(jí)操作

TouchAction是AppiumDriver的輔助類(lèi),主要針對(duì)手勢(shì)操作,比如滑動(dòng)、長(zhǎng)按、拖動(dòng)等,原理是將一系列的動(dòng)作放在一個(gè)鏈條中發(fā)送到服務(wù)器,服務(wù)器接受到該鏈條后,解析各個(gè)動(dòng)作,逐個(gè)執(zhí)行。

9.1. 前置代碼

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)

?? 所有手勢(shì)都要通過(guò)執(zhí)行函數(shù)才會(huì)運(yùn)行.

9.2. 手指輕敲操作

模擬手指輕敲一下屏幕操作

  • 方法:tap(element=None, x=None, y=None)

  • 方法:perform() # 發(fā)送命令到服務(wù)器執(zhí)行操作

  • 參數(shù):
    1.element:被定位到的元素
    2.x:相對(duì)于元素左上角的坐標(biāo),通常會(huì)使用元素的X軸坐標(biāo)
    3.y:通常會(huì)使用元素的Y軸坐標(biāo)

  • 業(yè)務(wù)場(chǎng)景:
    1.進(jìn)入設(shè)置
    2.點(diǎn)擊WLAN選項(xiàng)

  • 代碼實(shí)現(xiàn):

    # 通過(guò)元素定位方式敲擊屏幕
    el = driver.find_element_by_xpath("http://*[contains(@text,'WLAN')]")
    TouchAction(driver).tap(el).perform()
    
    # 通過(guò)坐標(biāo)方式敲擊屏幕,WLAN坐標(biāo):x=155,y=250
    # TouchAction(driver).tap(x=155,y=250).perform()
    
    

9.3. 手指按操作

模擬手指按下屏幕,按就要對(duì)應(yīng)著離開(kāi).

  • 方法:press(el=None, x=None, y=None)

  • 方法:release() # 結(jié)束動(dòng)作,手指離開(kāi)屏幕

  • 參數(shù):
    1.element:被定位到的元素
    2.x:通常會(huì)使用元素的X軸坐標(biāo)
    3.y:通常會(huì)使用元素的Y軸坐標(biāo)

  • 業(yè)務(wù)場(chǎng)景:
    1.進(jìn)入設(shè)置
    2.點(diǎn)擊WLAN選項(xiàng)

  • 代碼實(shí)現(xiàn):

    # 通過(guò)元素定位方式按下屏幕
    el = driver.find_element_by_xpath("http://*[contains(@text,'WLAN')]")
    TouchAction(driver).press(el).release().perform()
    
    # 通過(guò)坐標(biāo)方式按下屏幕,WLAN坐標(biāo):x=155,y=250
    # TouchAction(driver).press(x=155,y=250).release().perform()
    
    

9.4. 等待操作

  • 方法:wait(ms=0)

  • 參數(shù):
    ms:暫停的毫秒數(shù)

  • 業(yè)務(wù)場(chǎng)景:
    1.進(jìn)入設(shè)置
    2.點(diǎn)擊WLAN選項(xiàng)
    3.長(zhǎng)按WiredSSID選項(xiàng)5秒

  • 代碼實(shí)現(xiàn):

    # 點(diǎn)擊WLAN
    driver.find_element_by_xpath("http://*[contains(@text,'WLAN')]").click()
    # 定位到WiredSSID
    el =driver.find_element_by_id("android:id/title")
    # 通過(guò)元素定位方式長(zhǎng)按元素
    TouchAction(driver).press(el).wait(5000).perform()
    
    # 通過(guò)坐標(biāo)方式模擬長(zhǎng)按元素
    # 添加等待(有長(zhǎng)按)/不添加等待(無(wú)長(zhǎng)按效果)
    # TouchAction(driver).press(x=770,y=667).wait(5000).release().perform()
    
    

9.5. 手指長(zhǎng)按操作

模擬手機(jī)按下屏幕一段時(shí)間,按就要對(duì)應(yīng)著離開(kāi).

  • 方法:long_press(el=None, x=None, y=None, duration=1000)

  • 參數(shù):
    1.element:被定位到的元素
    2.x:通常會(huì)使用元素的X軸坐標(biāo)
    3.y:通常會(huì)使用元素的Y軸坐標(biāo)
    4.duration:持續(xù)時(shí)間,默認(rèn)為1000ms

  • 業(yè)務(wù)場(chǎng)景:
    1.進(jìn)入設(shè)置
    2.點(diǎn)擊WLAN選項(xiàng)
    3.長(zhǎng)按WiredSSID選項(xiàng)5秒

  • 代碼實(shí)現(xiàn):

    # 點(diǎn)擊WLAN
    driver.find_element_by_xpath("http://*[contains(@text,'WLAN')]").click()
    # 定位到WiredSSID
    el =driver.find_element_by_id("android:id/title")
    # 通過(guò)元素定位方式長(zhǎng)按元素
    TouchAction(driver).long_press(el,duration=5000).release().perform()
    
    # 通過(guò)坐標(biāo)方式長(zhǎng)按元素,WiredSSID坐標(biāo):x=770,y=667
    # 添加等待(有長(zhǎng)按)/不添加等待(無(wú)長(zhǎng)按效果)
    # TouchAction(driver).long_press(x=770,y=667).perform()
    
    

9.6. 手指移動(dòng)操作

模擬手機(jī)的滑動(dòng)操作

  • 方法:move_to(el=None, x=None, y=None)

  • 參數(shù):
    1.el:定位的元素
    2.x:相對(duì)于前一個(gè)元素的X軸偏移量
    3.y:相對(duì)于前一個(gè)元素的Y軸偏移量

  • 業(yè)務(wù)場(chǎng)景1:
    1.進(jìn)入設(shè)置
    2.向上滑動(dòng)屏幕

  • 代碼實(shí)現(xiàn):

    # 定位到存儲(chǔ)
    el = driver.find_element_by_xpath("http://*[contains(@text,'存儲(chǔ)')]")
    # 定位到更多
    el1 = driver.find_element_by_xpath("http://*[contains(@text,'更多')]")
    # 元素方式滑動(dòng)
    TouchAction(driver).press(el).move_to(el1).release().perform()
    # 坐標(biāo)的方式滑動(dòng)
    # TouchAction(driver).press(x=240,y=600).wait(100).move_to(x=240,y=100).release().perform()
    # 注意press連接一個(gè)move_to實(shí)際調(diào)用的是swip方法,可在log中查詢,不要給相對(duì)坐標(biāo)。
    
    
  • 業(yè)務(wù)場(chǎng)景2:
    1.進(jìn)入設(shè)置
    2.向上滑動(dòng)屏幕到可見(jiàn)"安全"選項(xiàng)
    3.進(jìn)入到安全
    4.點(diǎn)擊屏幕鎖定方式
    5.點(diǎn)擊圖案
    6.繪制圖案

  • 代碼實(shí)現(xiàn):

    # 定位到WLAN
    el1 = driver.find_element_by_xpath("http://*[contains(@text,'WLAN')]")
    # 定位到存儲(chǔ)
    el2 = driver.find_element_by_xpath("http://*[contains(@text,'存儲(chǔ)')]")
    # 存儲(chǔ)上滑到WLAN
    driver.drag_and_drop(el2,el1)
    # 定位到用戶
    el3 = driver.find_element_by_xpath("http://*[contains(@text,'用戶')]")
    # 注意 這次使用drag_and_drop方法,傳入的"存儲(chǔ)定位"仍使用其原始在屏幕上的位置,所以是由存儲(chǔ)滑動(dòng)到用戶才可以上滑,否則需要重新"定位存儲(chǔ)"
    # 存儲(chǔ)上滑倒用戶位置
    driver.drag_and_drop(el2,el3)
    # 點(diǎn)擊安全按鈕
    driver.find_element_by_xpath("http://*[contains(@text,'安全')]").click()
    # 點(diǎn)擊屏幕鎖定方式按鈕
    driver.find_element_by_xpath("http://*[contains(@text,'屏幕鎖定')]").click()
    # 點(diǎn)擊圖案按鈕
    driver.find_element_by_xpath("http://*[contains(@text,'圖案')]").click()
    # 繪制圖案四個(gè)坐標(biāo) 1:(244,967) 2:(723,967) 3:(723,1442) 4:(244,1916)
    TouchAction(driver).press(x=244,y=967).wait(100).move_to(x=479,y=0).wait(100)\
              .move_to(x=0,y=475).wait(100).move_to(x=-479,y=474).release().perform()
    
    

十、手機(jī)操作API

針對(duì)手機(jī)的一些常用設(shè)置功能進(jìn)行操作.

10.1. 前置代碼

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)

10.2. 獲取手機(jī)時(shí)間

  • 方法:device_time

  • 代碼實(shí)現(xiàn):

    # 獲取當(dāng)前手機(jī)的時(shí)間
    print(driver.device_time)
    
    
  • 執(zhí)行結(jié)果:

    Wed Dec 27 08:52:45 EST 2017
    
    

10.3. 獲取手機(jī)的寬高

獲取手機(jī)的寬高,可以根據(jù)寬高做一些坐標(biāo)的操作

  • 方法:get_window_size()
  • 代碼實(shí)現(xiàn):
print(driver.get_window_size())

  • 執(zhí)行結(jié)果:
{'height': 800, 'width': 480}

10.4. 發(fā)送鍵到設(shè)備

模擬系統(tǒng)鍵值的操作,比如操作home鍵,音量鍵,返回鍵等。

  • 參數(shù):
    keycode:發(fā)送給設(shè)備的關(guān)鍵代碼
    metastate:關(guān)于被發(fā)送的關(guān)鍵代碼的元信息,一般為默認(rèn)值

  • 業(yè)務(wù)場(chǎng)景:
    1.打開(kāi)設(shè)置
    2.按多次音量增加鍵

  • 代碼實(shí)現(xiàn):

    for i in range(3):
        driver.keyevent(24)
    
    

Appium---Android的keycode鍵值

adb命令使用
adb shell input keyevent XX(EventCode) #輸入對(duì)應(yīng)的鍵值
adb shell input text "www.baidu.com"
#向?yàn)g覽器發(fā)送文本

EventCode KeyEvent EventName
0 KEYCODE_UNKNOWN 未知鍵
1 KEYCODE_SOFT_LEFT 左鍵
2 KEYCODE_SOFT_RIGHT 右鍵
3 KEYCODE_HOME Home鍵
4 KEYCODE_BACK 返回鍵
5 KEYCODE_CALL 撥號(hào)鍵
6 KEYCODE_ENDCALL 掛機(jī)鍵
7 KEYCODE_0 按鍵“0”
8 KEYCODE_1 按鍵“1”
9 KEYCODE_2 按鍵“2”
10 KEYCODE_3 按鍵“3”
11 KEYCODE_4 按鍵“4”
12 KEYCODE_5 按鍵“5”
13 KEYCODE_6 按鍵“6”
14 KEYCODE_7 按鍵“7”
15 KEYCODE_8 按鍵“8”
16 KEYCODE_9 按鍵“9”
17 KEYCODE_STAR 按鍵“*”
18 KEYCODE_POUND 按鍵“#”
19 KEYCODE_DPAD_UP 導(dǎo)航鍵 向上
20 KEYCODE_DPAD_DOWN 導(dǎo)航鍵 向下
21 KEYCODE_DPAD_LEFT 導(dǎo)航鍵 向左
22 KEYCODE_DPAD_RIGHT 導(dǎo)航鍵 向右
23 KEYCODE_DPAD_CENTER 導(dǎo)航鍵 確定
24 KEYCODE_VOLUME_UP 音量鍵加
25 KEYCODE_VOLUME_DOWN 音量鍵減
26 KEYCODE_POWER 電源鍵
27 KEYCODE_CAMERA 相機(jī)鍵
28 KEYCODE_CLEAR 清除鍵
29 KEYCODE_A 按鍵“A”
30 KEYCODE_B 按鍵“B”
31 KEYCODE_C 按鍵“C”
32 KEYCODE_D 按鍵“D”
33 KEYCODE_E 按鍵“E”
34 KEYCODE_F 按鍵“F”
35 KEYCODE_G 按鍵“G”
36 KEYCODE_H 按鍵“H”
37 KEYCODE_I 按鍵“I”
38 KEYCODE_J 按鍵“J”
39 KEYCODE_K 按鍵“K”
40 KEYCODE_L 按鍵“L”
41 KEYCODE_M 按鍵“M”
42 KEYCODE_N 按鍵“N”
43 KEYCODE_O 按鍵“O”
44 KEYCODE_P 按鍵“P”
45 KEYCODE_Q 按鍵“Q”
46 KEYCODE_R 按鍵“R”
47 KEYCODE_S 按鍵“S”
48 KEYCODE_T 按鍵“T”
49 KEYCODE_U 按鍵“U”
50 KEYCODE_V 按鍵“V”
51 KEYCODE_W 按鍵“W”
52 KEYCODE_X 按鍵“X”
53 KEYCODE_Y 按鍵“Y”
54 KEYCODE_Z 按鍵“Z”
55 KEYCODE_COMMA 按鍵“,”
56 KEYCODE_PERIOD 按鍵‘.’
57 KEYCODE_ALT_LEFT 組合鍵 Alt+Left
58 KEYCODE_ALT_RIGHT 組合鍵 Alt+Right
59 KEYCODE_SHIFT_LEFT 組合鍵 Shift+Left
60 KEYCODE_SHIFT_RIGHT 組合鍵 Shift+Left
61 KEYCODE_TAB Tab鍵
62 KEYCODE_SPACE 空格鍵
63 KEYCODE_SYM 選擇輸入法
64 KEYCODE_EXPLORER 瀏覽器
65 KEYCODE_ENVELOPE 郵件
66 KEYCODE_ENTER 回車(chē)鍵
67 KEYCODE_DEL 退格鍵
68 KEYCODE_GRAVE 按鍵‘`’
69 KEYCODE_MINUS 按鍵‘-’
70 KEYCODE_EQUALS 按鍵‘=’
71 KEYCODE_LEFT_BRACKET 按鍵‘[’
72 KEYCODE_RIGHT_BRACKET 按鍵‘]’
73 KEYCODE_BACKSLASH 按鍵‘\’
74 KEYCODE_SEMICOLON 按鍵‘,’
75 KEYCODE_APOSTROPHE 按鍵‘'’(單引號(hào))
76 KEYCODE_SLASH 按鍵‘/’
77 KEYCODE_AT 按鍵‘@’
78 KEYCODE_NUM 按鍵Number modifier
79 KEYCODE_HEADSETHOOK 按鍵Headset Hook
80 KEYCODE_FOCUS 拍照對(duì)焦鍵
81 KEYCODE_PLUS 按鍵‘+’
82 KEYCODE_MENU 菜單鍵
83 KEYCODE_NOTIFICATION 通知鍵
84 KEYCODE_SEARCH 搜索鍵
85 TAG_LAST_KEYCODE

10.5. 操作手機(jī)通知欄

打開(kāi)手機(jī)的通知欄,可以獲取通知欄的相關(guān)信息和元素操作

  • 方法:open_notifications()
  • 業(yè)務(wù)場(chǎng)景:
    1.啟動(dòng)設(shè)置
    2.打開(kāi)通知欄
  • 代碼實(shí)現(xiàn):
driver.open_notifications()

10.6. 獲取手機(jī)當(dāng)前網(wǎng)絡(luò)

獲取手機(jī)當(dāng)前連接的網(wǎng)絡(luò)

  • 方法:network_connection
  • 業(yè)務(wù)場(chǎng)景:獲取手機(jī)當(dāng)前網(wǎng)絡(luò)模式
  • 代碼實(shí)現(xiàn):
print(driver.network_connection)

  • 執(zhí)行結(jié)果:
6

Value (Alias) Data Wifi Airplane Mode
0 (None) 0 0 0
1 (Airplane Mode) 0 0 1
2 (Wifi only) 0 1 0
4 (Data only) 1 0 0
6 (All network on) 1 1 0

10.7. 設(shè)置手機(jī)網(wǎng)絡(luò)

更改手機(jī)的網(wǎng)絡(luò)模式,模擬特殊網(wǎng)絡(luò)情況下的測(cè)試用例

  • 方法:set_network_connection(connectionType)
  • 參數(shù):
    connectionType:需要被設(shè)置成為的網(wǎng)絡(luò)類(lèi)型
  • 業(yè)務(wù)場(chǎng)景:
    1.啟動(dòng)設(shè)置
    2.設(shè)置手機(jī)網(wǎng)絡(luò)為飛行模式
  • 代碼實(shí)現(xiàn):
driver.set_network_connection(1)

10.8. 手機(jī)截圖

截取手機(jī)當(dāng)前屏幕,保存指定格式圖片到設(shè)定位置

  • 方法:get_screenshot_as_file(filename)

  • 參數(shù):
    filename:指定路徑下,指定格式的圖片.

  • 業(yè)務(wù)場(chǎng)景:
    1.打開(kāi)設(shè)置頁(yè)面
    2.截圖當(dāng)前頁(yè)面保存到當(dāng)前目錄,命名為screen.png

  • 代碼實(shí)現(xiàn):

    import os
    driver.get_screenshot_as_file(os.getcwd() + os.sep + './screen.png')
    
    
  • 執(zhí)行結(jié)果:
    當(dāng)前目錄下會(huì)生成screen.png文件

十一、腳本錄制

11.1. 認(rèn)識(shí)界面

image

11.2. 點(diǎn)擊開(kāi)始錄制按鍵開(kāi)始錄制腳本

  1. 點(diǎn)擊頂部導(dǎo)航欄左側(cè)第一個(gè)“選擇元素”按鍵選定搜索欄,然后點(diǎn)擊右邊點(diǎn)“點(diǎn)擊”按鍵進(jìn)行操作(錄制過(guò)程就是先選擇錄制窗口左邊的APP元素,然后錄制窗口右邊的操作方式)。

  2. 錄制完成后點(diǎn)擊“停止錄制”按鍵,錄制窗口右上角會(huì)同步顯示操作代碼,選擇代碼類(lèi)型,將模板代碼轉(zhuǎn)換成正式代碼,復(fù)制代碼到Pycharm。

  3. 代碼復(fù)制到pycharm后,最好是在每個(gè)操作或者頁(yè)面切換處加上等待時(shí)間,否則會(huì)因?yàn)榫W(wǎng)速、APP設(shè)計(jì)問(wèn)題或者其他原因,無(wú)法及時(shí)到達(dá)下一個(gè)頁(yè)面,導(dǎo)致APPIUM無(wú)法獲取頁(yè)面元素而定位元素失敗,在pycharm運(yùn)行時(shí)報(bào)錯(cuò)。代碼編輯好后點(diǎn)擊pycharm的運(yùn)行按鍵,APPium就會(huì)在手機(jī)上面自動(dòng)運(yùn)行腳本了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容