App測試端

一砚作、Appium介紹

Appium是一個(gè)移動(dòng)端的自動(dòng)化框架,可用于測試原生應(yīng)用嘹锁、移動(dòng)網(wǎng)頁應(yīng)用和混合型應(yīng)用葫录,且是跨平臺(tái)的×旎可用于IOS和Android以及firefox的操作系統(tǒng)米同。

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

重要的是Appium是跨平臺(tái)的继低,何為跨平臺(tái)熬苍,意思就是可以針對不同的平臺(tái)用一套api來編寫測試用例。

二袁翁、環(huán)境搭建

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

image

1. appium安裝

直接解壓即可柴底,打開Appium.exe

image

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

image

2. Appium庫安裝

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

三、Appium使用

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

①打開手機(jī)應(yīng)用
②打開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ū)分大小寫
desired_caps['platformName'] = 'Android'
# 系統(tǒng)版本,7.1.2可以寫[7 焙压,7.1 鸿脓, 7.1.2]
desired_caps['platformVersion'] = '7.1.2'
# 設(shè)備名稱,可以隨便寫涯曲,但是不能亂寫答憔,Android可以隨便寫,但是ios必須正確的寫
desired_caps['deviceName'] = 'emulator-5554'
# app的信息
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
# 聲明我們的driver對象
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)對象

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

driver.quit()   # 關(guān)閉驅(qū)動(dòng)對象虐拓,同時(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對象
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é)果為True(已安裝) / 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類型,需要先轉(zhuǎn)碼态兴;
生成的數(shù)據(jù)為byte類型狠持,需要將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)前頁面的文檔結(jié)構(gòu)瞻润,判斷特定的元素是否存在

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

4.1 工具簡介

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

4.1 如何使用

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

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

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

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

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

    image

五正勒、APP元素定位操作

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

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對象
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)

5.3 通過id定位

  • 方法:find_element_by_id(id_value) # id_value:為元素的id屬性值

  • 業(yè)務(wù)場景:
    1. 進(jìn)入設(shè)置頁面
    2. 通過ID定位方式點(diǎn)擊搜索按鈕

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

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

<meta charset="utf-8">

5.4 通過class定位

  • 方法:find_element_by_class_name(class_value) # class_value:為元素的class屬性值
  • 業(yè)務(wù)場景:
    1. 進(jìn)入設(shè)置頁面
    2. 點(diǎn)擊搜索按鈕
    3. 通過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 通過xpath定位

  • 方法:find_element_by_xpath(xpath_value) # xpath_value:為可以定位到元素的xpath語句
    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ù)場景:
    1. 進(jìn)入設(shè)置頁面
    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)用場景為元素值重復(fù),無法通過元素屬性直接定位到某個(gè)元素非洲,只能通過elements方式來選擇鸭限,返回一個(gè)定位對象的列表.

5.7 通過id方式定位一組元素

  • 方法: find_elements_by_id(id_value) # id_value:為元素的id屬性值

  • 業(yè)務(wù)場景:
    1. 進(jìn)入設(shè)置頁面
    2. 點(diǎn)擊WLAN菜單欄(id定位對象列表中第1個(gè))

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

    # 定位到一組元素
    title = driver.find_elements_by_id("com.android.settings:id/title")
    # 打印title類型,預(yù)期為list
    print(type(title))
    # 取title返回列表中的第一個(gè)定位對象两踏,執(zhí)行點(diǎn)擊操作
    title[0].click()
    
    

5.8 通過class方式定位一組元素

  • 方法:find_elements_by_class_name(class_value) # class_value:為元素的class屬性值

  • 業(yè)務(wù)場景:
    1.進(jìn)入設(shè)置頁面
    2.點(diǎn)擊WLAN菜單欄(class定位對象列表中第3個(gè))

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

    title = driver.find_elements_by_class_name("android.widget.TextView")
    # 打印title類型败京,預(yù)期為list
    print(type(title))
    # 取title返回列表中的第一個(gè)定位對象,執(zhí)行點(diǎn)擊操作
    title[3].click()
    for index, item in enumerate(ele_list):
      print(index, item.text)  ```
    
    

5.9 通過xpath方式定位一組元素

  • 方法:find_elements_by_xpath(xpath_value) # xpath_value:為可以定位到元素的xpath語句

  • 業(yè)務(wù)場景:
    1. 進(jìn)入設(shè)置頁面
    2. 點(diǎn)擊WLAN菜單欄(xpath中class屬性定位對象列表中第3個(gè))

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

    # 定位到一組元素
    title = driver.find_elements_by_xpath("http://*[contains(@class,'widget.TextView')]")
    # 打印title類型梦染,預(yù)期為list
    print(type(title))
    # 取title返回列表中的第一個(gè)定位對象赡麦,執(zhí)行點(diǎn)擊操作
    title[3].click()
    
    

六、WebDriverWait 顯示等待操作

在一個(gè)超時(shí)時(shí)間范圍內(nèi)弓坞,每隔一段時(shí)間去搜索一次元素是否存在隧甚,如果存在返回定位對象,如果不存在直到超時(shí)時(shí)間到達(dá)渡冻,報(bào)超時(shí)異常錯(cuò)誤戚扳。

  • 方法:WebDriverWait(driver, timeout, poll_frequency).until(method)
    參數(shù):
    1.driver:手機(jī)驅(qū)動(dòng)對象
    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)行過程:
    1.實(shí)例化WebDriverWait類,傳入driver對象超歌,之后driver對象被賦值給WebDriverWait的一個(gè)類變量:self._driver
    2.until為WebDriverWait類的方法砍艾,until傳入method方法(即匿名函數(shù)),之后method方法會(huì)被傳入self._driver
    3.搜索到元素后until返回定位對象巍举,沒有搜索到函數(shù)until返回超時(shí)異常錯(cuò)誤.

  • 業(yè)務(wù)場景:
    1.進(jìn)入設(shè)置頁面
    2.通過ID定位方式點(diǎn)擊搜索按鈕

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

    from selenium.webdriver.support.wait import WebDriverWait # 導(dǎo)入WebDriverWait  類
    # 超時(shí)時(shí)間為30s脆荷,每隔1秒搜索一次元素是否存在,如果元素存在返回定位對象并退出
    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ù)場景:
    1.打開設(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é)果:輸入框無任何值輸入且程序不會(huì)抱錯(cuò)
    解決輸入中文問題:

      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ù)場景:
    1.打開設(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()
    

<meta charset="utf-8">

<article class="_2rhmJa">

7.4. 獲取元素的文本內(nèi)容

  • 方法: text

  • 業(yè)務(wù)場景:
    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ǎ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ù)場景:
    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ù)場景:
    1.進(jìn)入設(shè)置頁面
    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ù)場景:
    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對象
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í)間長度,單位:ms

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

    # 滑動(dòng)沒有持續(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è)元素观堂,直到頁面自動(dòng)停止

  • 方法:scroll(origin_el, destination_el)

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

  • 業(yè)務(wù)場景:
    1.進(jìn)入設(shè)置頁
    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)開始的元素
    2.destination_el:滑動(dòng)結(jié)束的元素

  • 業(yè)務(wù)場景:
    1.進(jìn)入設(shè)置頁
    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ù)場景:
    1.進(jìn)入設(shè)置頁
    2.將APP置于后臺(tái)5s

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

    driver.background_app(5)
    
    
  • 效果:

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

九、APP模擬手勢高級操作

TouchAction是AppiumDriver的輔助類踏枣,主要針對手勢操作七兜,比如滑動(dò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對象
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)

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

9.2. 手指輕敲操作

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

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

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

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

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

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

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

9.3. 手指按操作

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

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

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

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

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

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

    # 通過元素定位方式按下屏幕
    el = driver.find_element_by_xpath("http://*[contains(@text,'WLAN')]")
    TouchAction(driver).press(el).release().perform()
    
    # 通過坐標(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ù)場景:
    1.進(jìn)入設(shè)置
    2.點(diǎn)擊WLAN選項(xiàng)
    3.長按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")
    # 通過元素定位方式長按元素
    TouchAction(driver).press(el).wait(5000).perform()
    
    # 通過坐標(biāo)方式模擬長按元素
    # 添加等待(有長按)/不添加等待(無長按效果)
    # TouchAction(driver).press(x=770,y=667).wait(5000).release().perform()
    
    

9.5. 手指長按操作

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

  • 方法: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ù)場景:
    1.進(jìn)入設(shè)置
    2.點(diǎn)擊WLAN選項(xiàng)
    3.長按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")
    # 通過元素定位方式長按元素
    TouchAction(driver).long_press(el,duration=5000).release().perform()
    
    # 通過坐標(biāo)方式長按元素,WiredSSID坐標(biāo):x=770,y=667
    # 添加等待(有長按)/不添加等待(無長按效果)
    # 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:相對于前一個(gè)元素的X軸偏移量
    3.y:相對于前一個(gè)元素的Y軸偏移量

  • 業(yè)務(wù)場景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中查詢迄薄,不要給相對坐標(biāo)。
    
    
  • 業(yè)務(wù)場景2:
    1.進(jìn)入設(shè)置
    2.向上滑動(dòng)屏幕到可見"安全"選項(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

針對手機(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對象
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ù)場景:
    1.打開設(shè)置
    2.按多次音量增加鍵

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

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

Appium---Android的keycode鍵值

adb命令使用
adb shell input keyevent XX(EventCode) #輸入對應(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 撥號鍵
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 回車鍵
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 按鍵‘'’(單引號)
76 KEYCODE_SLASH 按鍵‘/’
77 KEYCODE_AT 按鍵‘@’
78 KEYCODE_NUM 按鍵Number modifier
79 KEYCODE_HEADSETHOOK 按鍵Headset Hook
80 KEYCODE_FOCUS 拍照對焦鍵
81 KEYCODE_PLUS 按鍵‘+’
82 KEYCODE_MENU 菜單鍵
83 KEYCODE_NOTIFICATION 通知鍵
84 KEYCODE_SEARCH 搜索鍵
85 TAG_LAST_KEYCODE

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

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

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

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

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

  • 方法:network_connection
  • 業(yè)務(wù)場景:獲取手機(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ò)情況下的測試用例

  • 方法:set_network_connection(connectionType)
  • 參數(shù):
    connectionType:需要被設(shè)置成為的網(wǎng)絡(luò)類型
  • 業(yè)務(wù)場景:
    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ù)場景:
    1.打開設(shè)置頁面
    2.截圖當(dāng)前頁面保存到當(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)識界面

image

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

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

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

  3. 代碼復(fù)制到pycharm后凫乖,最好是在每個(gè)操作或者頁面切換處加上等待時(shí)間,否則會(huì)因?yàn)榫W(wǎng)速弓颈、APP設(shè)計(jì)問題或者其他原因帽芽,無法及時(shí)到達(dá)下一個(gè)頁面,導(dǎo)致APPIUM無法獲取頁面元素而定位元素失敗翔冀,在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)容合作請聯(lián)系作者
  • 序言:七十年代末搬瑰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子控硼,更是在濱河造成了極大的恐慌泽论,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卡乾,死亡現(xiàn)場離奇詭異翼悴,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)说订,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門抄瓦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人陶冷,你說我怎么就攤上這事钙姊。” “怎么了埂伦?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵煞额,是天一觀的道長。 經(jīng)常有香客問我,道長膊毁,這世上最難降的妖魔是什么胀莹? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮婚温,結(jié)果婚禮上描焰,老公的妹妹穿的比我還像新娘。我一直安慰自己栅螟,他們只是感情好荆秦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著力图,像睡著了一般步绸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吃媒,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天瓤介,我揣著相機(jī)與錄音,去河邊找鬼赘那。 笑死刑桑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的漓概。 我是一名探鬼主播漾月,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼病梢,長吁一口氣:“原來是場噩夢啊……” “哼胃珍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜓陌,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤觅彰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后钮热,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體填抬,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年隧期,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了飒责。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仆潮,死狀恐怖宏蛉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情性置,我是刑警寧澤拾并,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響嗅义,放射性物質(zhì)發(fā)生泄漏屏歹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一之碗、第九天 我趴在偏房一處隱蔽的房頂上張望蝙眶。 院中可真熱鬧,春花似錦褪那、人聲如沸械馆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽霹崎。三九已至,卻和暖如春冶忱,著一層夾襖步出監(jiān)牢的瞬間尾菇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工囚枪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留派诬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓链沼,卻偏偏與公主長得像默赂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子括勺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容