1. 程式人生 > 其它 >移動端自動化

移動端自動化

移動端測試環境搭建

  移動端自動化測試的基礎環境配置需要搭建下面三個環境:

    1、Java環境
    2、AndroidSDK環境
    3、Android模擬器

  下載連結: https://pan.baidu.com/s/1XP5ki3uHy4b7giiePv5QhA 提取碼: mb4p

環境說明

  Java:Android的應用層開發使用的是Java語言,所以需要使 Java環境。

  AndroidSDK:提供Android開發的軟體開發工具包。

  Android模擬器:模擬安卓手機的一個程式。

Java環境安裝

  下載JDK1.8安裝即可,詳見:https://www.cnblogs.com/lyang-a/p/11462369.html

AndroidSDK環境安裝

  AndroidSDK下載的官網地址:https://www.androiddevtools.cn/

  Window 平臺解壓後,進入解壓縮目錄,雙擊 SDK Manager.exe ,下載所需工具包即可。
  Mac平臺解壓後,進入解壓縮目錄,進入tools目錄,雙擊 android 這個檔案,開啟 Android SDK Manager, 下載所需工具包。

  參考地址:https://www.pianshen.com/article/399239299/

AndroidSDK環境變數配置:

  注意:android-sdk 資料夾需注意,路徑中不要有中文。

1. 進入我的電腦 -> 屬性 -> 高階系統設定 -> 環境變數

2. 在系統變數下點選新建 -> 變數名: ANDROID_HOME -> 變數值(檔案路徑): D:\android-sdk -> 點選確定按鈕

3. 在系統變數下找到系統的path變數,最後新增:;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;(最前面是一個分號,如果path變數最後已有分號,可不用新增) -> 點選確定按鈕

mac平臺的AndroidSDK環境變數配置:

1.進入命令列, 
	vim ~/.bash_profile
2.設定環境變數
    ANDROID_HOME=電腦存放的路徑/android-sdk-macosx
    PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
    export ANDROID_HOME 
    export PATH
3. 重寫開啟終端

驗證環境變數是否配置成功:

adb version

  android_sdk中的adb.exe版本和夜神模擬器中的nox_adb命令版本不一致,則會報錯:

  解決辦法:

    1、把android_sdk\platform-tools目錄下adb.exe複製一份,名字修改為:nox_adb.exe

    2、把夜神模擬器中bin目錄下的nox_adb.exe進行替換

    3、重啟夜神模擬器

    4、開啟終端輸入 【adb devices】即可發現連線的裝置

adb命令

  adb全名Andorid Debug Bridge,是一個除錯工具,它可以在電腦通過終端命令操作安卓手機或者模擬器。

adb的工作原理

  adb 包含三個部分:

    1、Client端:執行在開發機器中,即你的開發PC機。用來發送adb命令。

    2、Daemon守護程序:執行在除錯裝置中, 即手機或模擬器,用來接收和執行adb命令。

    3、Server端:作為一個後臺程序同樣執行在開發機器中, 用來管理PC中的Client端和手機的Daemon之間的通訊。

adb的常用命令

檢視adb版本

adb version

adb --version

獲取包名和介面名

  包名:app的唯一標識,好比身份證號碼
  介面名:app中顯示介面對應的名字

示例:

  1、開啟設定

  2、開啟終端輸入命令

    Windows過濾使用 findstr ,Mac過濾使用 grep

Windows:
	adb shell dumpsys window windows | findstr mFocusedApp
	
Mac:
	adb shell dumpsys window windows | grep mFocusedApp

  3、得到結果資料

mFocusedApp=AppWindowToken{d02598c token=Token{85dfcde ActivityRecord{11a3419 u0 com.android.settings/.Settings t38}}}

  此處包名為:com.android.settings

  介面名為:.Settings

檔案傳輸

  將電腦上的檔案傳送到手機

adb push 電腦的檔案的路徑 手機的資料夾的路徑

# 示例
adb push D:\2233.png /sdcard

  將手機上的檔案傳送到電腦

adb pull 手機的檔案的路徑 電腦的資料夾的路徑

# 示例
adb pull /sdcard/2233.png D:\

安裝程式

adb install apk路徑

adb install -r apk路徑

  -r 覆蓋安裝

# 示例
adb install -r bug.apk

解除安裝程式

  解除安裝程式時需先查詢到指定軟體的包名,根據包名進行刪除

adb uninstall 包名

# 示例
adb uninstall cn.itcast.myapplication

檢視連線裝置

# 檢視手機的連線狀態adb devices
# -s:指定某個裝置例:
# 指定某個裝置執行命令adb -s 裝置號 命令
	adb -s 裝置號 push xxx
	adb -s 裝置號 install xxx
	adb -s 127.0.0.1:62001 install D:/bug.apk

進入Android系統終端

  進入Android手機中的linux系統中,Android系統是基於Linux系統的。

adb shell

開啟/關閉adb服務

adb kill-server    # 關閉adb服務

adb start-server   # 開啟adb服

檢視App啟動時間

adb shell am start -W 包名/介面名

  ThisTime:該介面啟動耗時時間(毫秒),如果關心應用有介面Activity啟動耗時,參考ThisTime
  TotalTime:應用自身啟動耗時時間(毫秒),如果只關心某個應用自身啟動耗時,參考TotalTime
  WaitTime: 系統啟動應用的耗時時間(毫秒),如果關心繫統啟動應用耗時,參考WaitTime

檢視手機上所有的包名

adb shell pm list packages

檢視日誌

adb logcat

  過濾級別:級別從高到低(E > W > I > D > V),E 表示錯誤、W表示警告

# 過濾日誌級別adb logcat *:級別

另一種檢視包名的方式:

  1、先 【adb logcat | findstr START】

  2、再開啟想要檢視的程式

檢視電池

adb shell dumpsys battery

檢視記憶體

adb shell dumpsys meminfo \

檢視cpu

adb shell top

  s:表示按什麼排序

例:adb shell top -s 9  # 按照CPU使用率進行排序

monkey介紹

  monkey是用來做Android的壓力測試的(ios不能做),要想對ios做壓力測試需用到 fastmonkey這個第三方工具。

  monkey主要用來測試App的健壯性。monkey測試、健壯性測試、壓力測試。

  命令:

adb shell monkey 選項 操作次數

  一次操作表示一次次數,比如:手指按下一次、移動一次、手指抬起一次都表示一次操作,共完成了3次操作。

monkey命令的選項

  -p  包名,要測試哪個應用程式

  -v  日誌級別,一般用兩個-v即可

  -s  seed值,用來複現bug,當seed值相同時,monkey所產生的事件序列也相同

  --throttle  事件的間隔時間,單位:毫秒,一般300毫秒左右就可以。

  --pct-xxx  設定事件的百分比

    --pct-touch 點選事件

    --pct-motion 滑動事件

monkey輸出日誌

  將monkey操作的日誌儲存到日誌中使用【>】進行寫入

adb shell monkey -p 包名 操作次數 > 日誌的路徑

monkey的操作

adb shell monkey -p 包名 -v -v [--pct-touch 百分比數字] --throttle 2000 次數 > 日誌的路徑

  提示:使用 【-v -v】可以詳細的檢視執行的操作

  檢視日誌,如果有 monkey finished表示執行過程中沒有問題,如果沒有在終端需要觀察 anr 或 exception異常資訊

  嘗試復現,使用 -s 引數。例:adb shell monkey -v -v -s 1628066493671 20

  

移動端自動化測試環境搭建

  Android自動化測試需要搭建下面5個環境,如下:

   1、Java環境

   2、AndroidSDK環境

   3、Android模擬器

   4、Appium Desktop(Appium 服務端)

   5、Appium-Python-Client(Appium Python客戶端)

具體執行流程:

  1、先通過Appium-Python-Client工具編寫操作手機App的Python程式碼;

  2、當執行編寫好的Python程式碼時會連線Appium服務端;

  3、Appium服務端通過解析操作的程式碼會啟動手機上對應的App,把Python程式碼操作手機App的效果會呈現出來,最終完成自動化測試。

Appium Desktop(Appium 服務端)介紹

  Appium Desktop是一款適用於Mac,Windows和Linux的開源應用程式,它以美觀而靈活的使用者介面提供強大的Appium服務。

作用:

  Appium服務端通過解析程式碼,驅動Android裝置來執行自動化測試指令碼。

  下載地址:https://github.com/appium/appium-desktop/releases/

Appium-Python-Client介紹

  它是移動端定位App元素和操作App元素的一個第三方庫,它還負責與Appium伺服器建立連線,並將測試指令碼的指令傳送到Appium伺服器,Appium伺服器再驅動手機或者模擬器展示相關的效果,類似於web端自動化測試中的Selenium庫。

  Appium庫是基於Selenium庫開發的,Appium庫中的WebDriver類是繼承Selenium庫中的WebDriver類。

安裝Python語言的Appium客戶端庫:

pip install Appium-Python-Client

appium入門示例

需求:

  使用 Appium-Python-Client 庫 開啟Android模擬器的設定介面

實現步驟:

  1、開啟appium伺服器

  2、啟動Android模擬器,開啟設定介面

  3、開啟電腦終端,輸入檢視包名和介面名的adb命令

adb shell dumpsys window windows | grep mFocusedApp

  4、編寫Python的Appium客戶端程式碼,實現開啟Android模擬器的設定介面

import time

from appium import webdriver

# 建立子彈,封裝啟動app的引數
desired_capabilities = {
    # 連線手機的平臺名稱
    "platformName": "Android",
    # 連線手機的平臺版本,也就是手機的作業系統版本, 至少匹配大版本,比如:寫7
    "platformVersion": "7.1",
    # 裝置名稱,隨便寫, 但是不能為空
    "deviceName": "127.0.0.1:62001",
    # 啟動程式的包名
    "appPackage": "com.android.settings",
    # 啟動程式的介面名
    "appActivity": ".Settings"
}
# 連線appium伺服器,並建立驅動物件
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

# 延時2秒鐘
time.sleep(2)
# 退出app
driver.quit()

引數說明:

platformName: 連線手機的平臺名稱
platformVersion: 手機的作業系統版本
deviceName: 裝置名稱,隨便寫, 但是不能為空
appPackage: 啟動程式的包名
appActivity: 啟動程式的介面名

其它引數說明:

# 設定輸入中文,預設不支援,下面兩個引數一般都是配合使用
unicodeKeyboard 使用 Unicode 輸入法,預設值 false
resetKeyboard 重置輸入法到原有狀態,如果單獨使用,將會被忽略,預設值 false

noReset:不重置應用,預設為false
noSign 跳過檢查和對應用進行 debug 簽名的步驟,預設值 false,appium 預設會對應用進行重簽名,可能導致官方伺服器不認,一般設定成True
autoGrantPermissions 自動同意app所需要的各種許可權,預設是false

uiautomatorviewer

  uiautomatorviewer是一個手機端檢視控制元件的特徵資訊的一個工具。

示例:

  檢視手機端設定程式右上角的放大鏡按鈕的 resource-id

步驟:

  1、開啟在電腦終端輸入 uiautomatorviewer;
  2、啟動android模擬器,開啟設定應用;
  3、開啟終端輸入uiautomatorviewer進行開啟,開啟後點擊左上角的第三個按鈕,關聯手機螢幕;
  4、點選放大鏡按鈕;
  5、檢視Node Detail 中的 resource-id 資訊。

說明:

  resource-id 好比 html元素的id,但是在手機端 resource-id這個屬性值可以重複。

  class 好比 html元素的class,表示類屬性。

  在手機端定位一般都使用xpath,更加靈活和方便。

元素定位操作

  根據元素的特徵資訊進行元素的定位,比如:利用xpath根據元素的屬性資訊進行定位

注意點:

  元素的定位基於當前螢幕範圍內的可見元素。

手機端元素的定位方式:

  id定位

  class定位

  xpath定位

定位一個元素的方法:

  使用id定位一個元素:driver.find_element_by_id(resource-id),定位的是resource-id屬性值

  使用class定位一個元素:driver.find_element_by_class_name(class_value),定位的是class屬性值

  使用xpath定位一個元素:driver.find_element_by_xpath(xpath_value),根據xpath表示式定位元素

  定位content-desc元素:driver.find_element_by_accessibility_id

  注意:定位一個元素時,如果多個元素都有相同的特徵資訊,使用該方法定位到的是第一個。

定位一組元素的方法:

  使用id定位一組元素:driver.find_elements_by_id(resource-id)

  使用class定位一組元素:driver.find_elements_by_class_name(class_value)

  使用xpath定位一組元素:driver.find_elements_by_xpath(xpath_value)

定位一個元素的示例:

"""
	使用id定位設定介面的放大鏡並點選
	使用class定位搜尋框並輸入內容“顯示” 
	使用xpath定位返回按鈕並點選
"""
import time

from appium import webdriver

# 建立字典,封裝啟動app的引數
desired_capabilities = {
    # 連線手機的平臺名稱
    "platformName": "Android",
    # 連線手機的平臺版本,也就是手機的作業系統版本, 至少匹配大版本,比如:寫7
    "platformVersion": "7.1",
    # 裝置名稱,隨便寫, 但是不能為空
    "deviceName": "127.0.0.1:62001",
    # 啟動程式的包名
    "appPackage": "com.android.settings",
    # 啟動程式的介面名
    "appActivity": ".Settings",
    # 設定支援中文輸入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 連線appium伺服器,並建立驅動物件
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

# 使用id定位放大鏡
search_button = driver.find_element_by_id("com.android.settings:id/search")
# 點選放大鏡
search_button.click()
time.sleep(0.5)

# 使用class定位搜尋框
search_box = driver.find_element_by_class_name("android.widget.EditText")
# 預設輸入不了中文,需要設定啟動app引數,unicodeKeyboard和resetKeyboard這兩個引數為True
search_box.send_keys("顯示")
time.sleep(0.5)

# 使用xpath定位返回按鈕
# back_button = driver.find_element_by_xpath("//android.widget.ImageButton[@content-desc='收起']")
# 簡單操作
back_button = driver.find_element_by_xpath("//*[@content-desc='收起']")
back_button.click()

# find_element_by_accessibility_id 可以用於定位content-desc的屬性值
# back_button = driver.find_element_by_accessibility_id("收起")
# back_button.click()


time.sleep(2)
# 退出app
driver.quit()

  說明:輸出的資訊裡面有空行,是因為定位class為android.widget.TextView的元素,沒有內容。

定位一組元素的示例:

"""
需求:
	通過程式開啟android手機或者模擬器的設定介面
	通過id定位所有resource-id為 android:id/title 的元素,並列印每一個元素的文字內容
	通過class定位所有的class為 android.widget.TextView 的元素,並列印每一個元素的文字內容
	通過xpath定位所有包含 '設' 的元素,並列印每一個元素的文字內容。
"""
import time

from appium import webdriver

# 建立字典,封裝啟動app的引數
desired_capabilities = {
    # 連線手機的平臺名稱
    "platformName": "Android",
    # 連線手機的平臺版本,也就是手機的作業系統版本, 至少匹配大版本,比如:寫7
    "platformVersion": "7.1",
    # 裝置名稱,隨便寫, 但是不能為空
    "deviceName": "127.0.0.1:62001",
    # 啟動程式的包名
    "appPackage": "com.android.settings",
    # 啟動程式的介面名
    "appActivity": ".Settings",
    # 設定支援中文輸入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 連線appium伺服器,並建立驅動物件
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

# 定位id為android:id/title的所有元素
title_list = driver.find_elements_by_id("android:id/title")
for element in title_list:
    # 獲取元素的內容
    print(element.text)

time.sleep(0.5)
# 定位class為android.widget.TextView的所有元素
text_view_list = driver.find_elements_by_class_name("android.widget.TextView")
for text_view in text_view_list:
    # 獲取元素的內容
    print(text_view.text)
time.sleep(0.5)
# 使用xpath定位文字內容包含 設 的所有元素

element_list = driver.find_elements_by_xpath("//*[contains(@text, '設')]")
for element in element_list:
    # 獲取元素的內容
    print(element.text)

time.sleep(2)
# 退出app
driver.quit()

定位單個元素和定位一組元素的注意點:

  使用find_elements_by_xx,如果傳入的特徵資訊沒有定位到元素,則返回一個空列表,比如: []

  使用find_element_by_xx,如果傳入的特徵資訊沒有定位到元素,則會丟擲一個NoSuchElementException的異常。

元素等待

應用場景:

  由於某些原因,我們想定位的元素沒有立刻出來,此時如果直接定位可能會報錯,比如有以下原因:

  1、由於網路速度原因
  2、伺服器處理請求原因
  3、電腦配置原因

元素等待的分類:

  隱式等待

  顯示等待

隱式等待

應用場景

  當定位所有元素時,設定超時時間為同一個值的時候,此時使用隱式等待,設定隱式等待能夠作用於所有元素。

注意點

  當定位的元素,超過指定時間了還沒有定位到,此時會丟擲一個 NoSuchElementException異常

操作程式碼

driver.implicitly_wait(10)

顯示等待

應用場景:

  當定位每個元素時,設定超時時間不一樣時,此時使用顯示等待, 它只能作用於某個元素的。

注意點:

  當定位的元素,超過指定時間了還沒有定位到,此時會丟擲一個 TimeoutException異常

操作程式碼:

WebDriverWait(driver, 超時時間, 搜尋時間間隔).until(lambda定位元素的函式)

示例:

"""
	開啟Android手機或者模擬器中的設定,使用顯示等待定位 “返回” 按鈕,超時時間設定為5秒,每1秒查詢一次。
"""
import time

from appium import webdriver

# 封裝啟動app的引數
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

desired_capabilities = {
    "platformName": "Android",
    "platformVersion": "7.1",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.settings",
    "appActivity": ".Settings",
    # 設定支援中文輸入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 連線appium伺服器,並建立驅動物件
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

# 顯示等待,如果元素沒有定位到則會丟擲 TimeoutException異常
# WebDriverWait(driver, 5, 1).until(lambda current_driver: driver.find_element_by_xpath("//*[@content-desc='收起']"))


def element_wait(timeout, poll_frequency, element):
    WebDriverWait(driver, timeout, poll_frequency).until(lambda current_driver: driver.find_element(*element))


element_wait(5, 1, (By.XPATH, "//*[@content-desc='搜尋設定']"))
element_wait(5, 1, (By.XPATH, "//*[@content-desc='收起']"))

time.sleep(3)
driver.quit()

隱式等待和顯示等待的區別

  作用域不同

   顯示等待作用於單個元素有效

   隱式等待作用於所有元素有效

  相同點:他們都是在找不到元素時觸發元素等待

  方法不同

   顯示等待方法封裝在WebDriverWait類中

   隱式等待直接通過driver.implicitly_wait()方法來設定

  丟擲的異常不用

   隱式等待超時沒有找到,會丟擲NoSuchElementException異常

   顯示等待超時沒有找到,會丟擲TimeoutException異常

元素操作方法

點選元素

# 對元素進行點選操作
element.click()

輸入和清空輸入框內容

# 對文字框進行輸入內容操作
element.send_keys(value)
# 對文字框進行清空內容操作
element.clear()

獲取元素的文字內容

  比如:按鈕、文字框、輸入框等控制元件可以獲取它們的文字內容

# 通過text屬性獲取元素的文字內容
element.text

獲取元素的位置和大小

# 獲取元素的位置
element.location
# 獲取元素的大小
element.size

獲取元素的屬性值

  當定位到元素後,想要使用元素的屬性資訊時,此時就要獲取元素的屬性值了。

# 根據屬性名獲取屬性值,value表示屬性名
element.get_attribute(value)

示例:

import time

from appium import webdriver

# 封裝啟動app的引數
desired_capabilities = {
    "platformName": "Android",
    "platformVersion": "7.1",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.settings",
    "appActivity": ".Settings",
    # 設定支援中文輸入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 連線appium伺服器,並建立驅動物件
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

search_button = driver.find_elements_by_id("com.android.settings:id/search")
# 點選操作
search_button.click()

search_text = driver.find_element_by_class_name("android.widget.EditText")
# 根據屬性名獲取屬性值, resourceId:獲取resource_id屬性對應的值
resource_id = search_text.get_attribute("resourceId")
print(resource_id)
# 對文字框進行輸入內容操作
search_text.send_keys("顯示")
# 通過text屬性獲取元素的文字內容
element = search_text.text
print(element)
# 對文字框進行清空內容操作
search_text.clear()

back_button = driver.find_element_by_class_name("android.widget.ImageButton")
# 根據屬性名獲取屬性值, name:獲取text或content-desc屬性對應的值
name = back_button.get_attribute("name")
print(name)
# 獲取元素的位置
location = back_button.location
# 獲取元素的大小
size = back_button.size
print("location:", location)
print("size:", size)

time.sleep(3)
driver.quit()

滑動和拖拽操作

  在做自動化測試中,有些元素需要滑動幾次屏幕後才會發現,才能進行定位元素的,此時需要用到滑動或者拖拽操作。

滑動操作方法

swipe()方法:

   根據開始和結束的座標點進行滑動

  語法:

driver.swipe(開始x座標, 開始y座標, 結束x座標, 結束y座標, 滑動這次操作共持續的時間(毫秒))

scroll()方法:

   根據開始元素位置和結束元素位置進行滑動

  語法:

driver.scroll(開始元素, 結束元素, 滑動這次操作共持續的時間(毫秒))

  提示:這個兩個方法都用滑動慣性,想要滑動的慣性小,把持續時間設定大一些,比如: 5000毫秒

拖拽操作方法

drag_and_drop()方法:

   根據兩個元素的位置進行滑動,從第一個元素的位置滑動到第二個元素的位置。

  語法:

driver.drag_and_drop(開始元素, 結束元素)

  提示: 這個drag_and_drop沒有滑動慣性,沒有持續時間引數。

為了更好的看到滑動效果,建議開啟指標,開啟指標位置(模擬器):

  1、開啟設定,找到關於平板電腦,點選進去

  2、找到版本號,連點5下,方可開啟開發者模式

  3、回到設定介面,點選開發者選項

  4、找到輸入 --> 指標位置,開啟該功能即可

示例:

import time

from appium import webdriver

# 封裝啟動app的引數
desired_capabilities = {
    "platformName": "Android",
    "platformVersion": "7.1",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.settings",
    "appActivity": ".Settings",
    # 設定支援中文輸入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 連線appium伺服器,並建立驅動物件
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)


def swipe_operation(start_x, start_y, end_x, end_y, duration=0):
    driver.swipe(start_x, start_y, end_x, end_y, duration)


# swipe_operation(200, 300, 200, 1000)
# swipe_operation(200, 1000, 200, 300, 3000)

window_size = driver.get_window_size()
print(window_size)
x = window_size["width"] / 2
start_y = window_size["height"] / 4 * 3
end_y = window_size["height"] / 4
swipe_operation(x, start_y, x, end_y)


show_control = driver.find_element_by_xpath("//*[@text='顯示']")
wallpaper_control = driver.find_element_by_xpath("//*[@text='更換桌布']")

# scroll:兩元素之間的滑動,有慣性
# driver.scroll(show_control, wallpaper_control)
driver.scroll(show_control, wallpaper_control, 3000)


# drag_and_drop:兩元素之間的拖拽,無慣性
driver.drag_and_drop(show_control, wallpaper_control)

time.sleep(3)
driver.quit()

滑動和拖拽方法的選擇

  有慣性
   座標之間滑動使用:swipe()方法
   元素之間滑動使用:scroll()方法
  無慣性
   元素之間拖拽使用:drag_and_drop()方法

測試設定介面的搜尋功能

"""
需求:
    利用pytest框架完成自動化測試設定介面的搜尋功能
	測試資料為: 電池、WLAN
"""
import time
import pytest

from appium import webdriver


class TestSettingSearch:
    data_list = [
        {"search_data": "電池", "except_value": True},
        {"search_data": "WLAN", "except_value": True},
        {"search_data": "ee", "except_value": False}
    ]

    def setup(self):
        # 封裝啟動app的引數
        desired_capabilities = {
            "platformName": "Android",
            "platformVersion": "7.1",
            "deviceName": "127.0.0.1:62001",
            "appPackage": "com.android.settings",
            "appActivity": ".Settings",
            # 設定支援中文輸入
            "unicodeKeyboard": True,
            "resetKeyboard": True
        }
        # 連線appium伺服器,並建立驅動物件
        self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)
        # 設定隱式等待
        self.driver.implicitly_wait(2)

    def teardown(self):
        time.sleep(3)
        self.driver.quit()

    @pytest.mark.parametrize("data", data_list)
    def test_search_value(self, data):
        print("資料為:", data)
        # 定位放大鏡控制元件
        self.driver.find_element_by_id("com.android.settings:id/search").click()
        # 定位搜尋框
        search_text = self.driver.find_element_by_id("android:id/search_src_text")
        # 向搜尋框輸入內容
        search_text.send_keys(data["search_data"])

        search_content = self.driver.find_elements_by_id("com.android.settings:id/title")
        if data["except_value"]:
            assert len(search_content) > 0
        else:
            assert len(search_content) == 0


if __name__ == '__main__':
    pytest.main(["-sv", "--alluredir=allure_data", "--clean-alluredir"])
    # 生成測試報告命令
    # allure generate allure_data --clean