Appium 初始化配置信息(Desired Capabilities),Desired Capabilities實際上就是一個字典,它主要用於向Appium Server提供初始化配置參數,如:想要測試的系統是Android還是IOS,測試哪款軟件,軟件的入口是哪里等。
這種服務關鍵字在網上很多,百度搜一下就有一大堆了。
定位Android的appPackage與appActivity-Windows操作系統方法
通過監控adb操作日志來找到appPackage與appActivity,CMD下輸入adb logcat | findstr Start,強制停止被測試軟件,再次打開,觀察logcat。
斜杠之前為appPackage,斜杠之后為appActivity。從此想抓那個App,就抓那個App。(logcat的日志較多,要找點擊時第一個Start proc的日志。)
這種查看日志的方式比較不方便,日志一多起來,眼睛一亂什么也找不到了。所以可以使用SDK中的aapt進行抓取
SDK中下載最新的build-tools,通過aapt dump badging xxx.apk命令來查appPackage與appActivity。
包名:
入口:
下列代碼可以打開手機QQ:
from appium import webdriver des = { 'resetKeyboard': True, 'platformVersion': '6.0.1', 'noReset': True, # 不將app初始化 'appActivity': 'com.tencent.mobileqq.activity.SplashActivity', # 'appActivity': '.BrowserActivity', 'appPackage': 'com.tencent.mobileqq', # 'appPackage': 'com.android.browser', 'unicodeKeyboard': True, 'deviceName': '1afd95f92', 'platformName': 'Android'} # print(des) driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', des)
獲取元素系列
# Android對應content-desc IOS對應accessibility identifier # content-desc是給殘障人士定義的特殊字段
driver.find_element_by_accessibility_id('content-desc') # ID定位於selenium不同,可能存在重復的問題。 # appium-desktop抓取元素時如果出現有id,則可以直接用。 # resource-id可能出現重復,需要具體看下有多少個。
driver.find_element_by_id('resource-id') # 對應class字段,有可能存在多個相同class。 # 多個相同class,每次獲取只取第一個遇到的元素。
driver.find_element_by_class_name('class') # Xpath路徑定位,與Web的Xpath定位在有一點點區別 # Native App的定位以class為基准,主要用到參數有text、resource-id、index
driver.find_element_by_xpath('//android.widget.EditText[@text="手機號"]') # 這個在運行時,調用的是Android自帶的UI框架UiAutomator的Api # 介紹幾個簡單常用的,text、className、resource-id # text # 匹配全部text文字
driver.find_element_by_android_uiautomator('new UiSelector().text("手機號")') # 包含text文字
driver.find_element_by_android_uiautomator('new UiSelector().textContains("機")') # 以text什么開始
driver.find_element_by_android_uiautomator('new UiSelector().textStartsWith("手")') # 正則匹配text
driver.find_element_by_android_uiautomator('new UiSelector().textMatches("^手.*")') # className
driver.find_elements_by_android_uiautomator('new UiSelector().className("android.widget.TextView")') # classNameMatches
driver.find_elements_by_android_uiautomator('new UiSelector().classNameMatches("^android.widget.*")') # resource-id、resourceIdMatches
driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.syqy.wecash:id/et_content")') # description
driver.find_element_by_android_uiautomator('new UiSelector().description("S 日歷")') # descriptionStartsWith
driver.find_element_by_android_uiautomator('new UiSelector().descriptionStartsWith("日歷")') # descriptionMatches
driver.find_element_by_android_uiautomator('new UiSelector().descriptionMatches(".*歷$")') # Native App 暫不能使用
driver.find_element_by_tag_name('') # Native App 暫不能使用
driver.find_element_by_partial_link_text('') # Native App 暫不能使用
driver.find_element_by_link_text('') # Native App 暫不能使用
driver.find_element_by_css_selector('')
滑動操作與拖拽操作
# 滾動處理 # elementObj1 目標滾動元素,elementObj2 起始滾動元素 # 底層通過action操作,與web ui相反,origin_el為目標元素,destination_el為起始元素 # 通過模擬手勢可以看出 從下面的元素移動到上面的元素 # action.press(origin_el).move_to(destination_el).release().perform() # web elementObj1為要移動的元素 elementObj2為移動到某個元素 # action.click(elementObj1).move_to_element(elementObj2).release().perform()
driver.scroll(elementObj1, elementObj2) #通過坐標實現滑屏操作 # 從手機的左上角開始,橫坐標為x軸,縱坐標為y # 分辨率不同,坐標不相同,所以需要根據屏幕的大小做比例運算
driver.swipe(start_x, start_y, end_x, end_y,duration=None) # 拖拽 # elementObj1源元素,elementObj2目標元素 # 通過long_press實現
driver.drag_and_drop(elementObj1, elementObj2) # 多點觸控 模擬手指點擊 # tap模擬按住坐標多少秒,[(x,y)] 多個坐標則寫多個元祖。參數2為按住多少秒。ms(毫秒)為單位
driver.tap([(x, y)], 5000)
操作APP
# 返回是否安裝了對應包名的App True 或者 False
driver.is_app_installed('com.syqy.wecash') # 關閉初始化信息中的App
driver.close_app() # 啟動初始化信息中的App
driver.launch_app() # 安裝app 參數為軟件的絕對路徑
driver.install_app(r'C:\Users\bjhouyafan\Desktop\tester\appUi\wecash.apk') # 卸載app 參數接收appPackageName
driver.remove_app('com.syqy.wecash') # 獲取當前打開的app名
driver.current_activity # 啟動某一個包的,某一個入口 # 參數接受appPackage,appActivity # 可以省略多個步驟直接到達指定測試的位置
driver.start_activity('com.android.browser','.BrowserActivity') # 每隔0.5秒判斷一次當前的app名稱是否是activityName # WebDriverWait
driver.wait_activity('activityName', 5, 0.5) # 將啟動的app退出到后台,多少秒后在切回app
driver.background_app('m') # 清除應用數據緩存,相當於卸載重裝
driver.reset()
NATIVE_APP 與 WEBVIEW 上下文操作
# 返回當前session中的app類型
driver.current_context # 返回當前app的類型 # WEBVIEW 或 WEBVIEW # 底層實際調用current_context
driver.context # 獲取app所有的類型 # 有WEBVIEW的則以list的形式展示兩個
driver.contexts # app類型切換 參數接收app類型 # appium對selenium的switch_to的擴展 # 增加了MobileSwitchTo,繼承了selenium的switch_to
driver.switch_to.context('context')
KeyCode操作
# 隱藏鍵盤
driver.hide_keyboard() # 發送按鍵碼,僅按一下,與press_keycode相同 # 可接收str或int的code碼
driver.keyevent(3) # 發送按鍵碼,僅按一下,可接收str或int的code碼
driver.press_keycode(24) # 發送一個長按的按鍵碼,接收參數必須是int的code碼
driver.long_press_keycode(25)
網絡
# 返回當前手機的網絡狀態
driver.network_connection # 導入
from appium.webdriver.connectiontype import ConnectionType # WIFI
ConnectionType.WIFI_ONLY # 數據流量
ConnectionType.DATA_ONLY # 飛行模式
ConnectionType.AIRPLANE_MODE # 無網絡模式
ConnectionType.NO_CONNECTION # 全部都打開
ConnectionType.ALL_NETWORK_ON # 設置 網絡
driver.set_network_connection(ConnectionType.AIRPLANE_MODE)
操作輸入法
# 返回Android上可用的輸入法
driver.available_ime_engines # 返回當前輸入法的包名
driver.active_ime_engine # 是否啟動了輸入法 True or False
driver.is_ime_active() # 切換輸入法 參數接收available_ime_engines中任意一個輸入法包名
driver.activate_ime_engine(driver.available_ime_engines[0]) # 關閉當前輸入法
driver.deactivate_ime_engine()
其他
# 鎖定手機多少秒 僅IOS
driver.lock() # 搖手機
driver.shake() # 打開通知欄 僅Android
driver.open_notifications() # 獲取連接手機的當前時間
driver.device_time # 開啟或關閉手機定位服務
driver.toggle_location_services()