appium+api+python

 

(1)獲取當前頁面的activity名,好比: (.ui.login.ViewPage)css

 
  current_activity()
 

 好比咱們須要實現這個登陸的功能時,主要思路爲若是當前界面爲登陸頁面時,就進行登陸行爲,不然就跳轉到登陸頁面。其僞代碼爲:html

 
1 if driver.current_activity == ".ui.login.ViewPage":
2     // To login_action
3 else:
4     // Trun to loginPage
 

 

 

(2)獲取當前頁面的樹形結構源代碼,與uiautomatorviewer截屏所展現出來的結構是相同的html5

 
  page_source()
 

例如當咱們完成登陸流程以後,要判斷登陸是否成功,則能夠判斷登陸後的頁面有沒有出現特定的內容(好比:運動圈、發現、運動、商城、個人),其僞代碼實現以下:python

 
複製代碼
複製代碼
driver \ 
    .page_source.find(u"運動圈") != -1 and 
    .page_source.find(u"發現") != -1 and 
    .page_source.find(u"運動") != -1 and 
    .page_source.find(u"商城") != -1 and
    .page_source.find(u"個人") != -1 and
複製代碼
複製代碼
 

page_source()的返回數據類型爲str。python中,str的find(context)方法,若是str存在context返回值爲context在str的index,若是不存在,則返回值爲-1。所以只須要判斷以上代碼塊返回的布爾值是True or False,就能夠判斷是否登陸成功。android

 

 

 

(3)獲取到當前窗口的全部context的名稱web

 
  contexts()
 

 在native和html5混合頁面測試時,須要在native層和H5層切換,因此首先須要獲得context層級的名稱api

 
print driver.contexts
>>> ['NATIVE_APP', 'WEBVIEW_com.codoon.gps']
 

因而可知,咱們知道App的H5層名稱爲"WEBVIEW_com.codoon.gps"後,使用driver.switch_to.context("WEBVIEW_com.codoon.gps")就能夠實現NATIVE和H5層的切換了。瀏覽器

 

 

 

2、獲取控件類API

 

(1)經過元素id查找當前頁面的一個目標元素微信

 
  find_element_by_id()
 

 經過源碼註釋能夠獲得find_element_by_id這一類的api主要有兩個使用途徑:網絡

 
driver.find_element_by_id("com.codoon.gps:id/tv_login")  // from webdriver.py
 

在driver下經過id查找一個元素,此用法一般適用於當前界面的driver有且僅有一個惟一的id元素標示,經過調用find_element_by_id能夠準確到找到目標元素;另外一種使用途徑主要以下:

 
複製代碼
複製代碼

driver_element = driver.find_element_by_xpath("//android.widget.ListView/android.widget.LinearLayout")

 

// from webdriverelement.py

driver_element.find_element_by_id("com.codoon.gps:id/activity_active_state") 

複製代碼
複製代碼
 

在driver.find_element_by_xpath返回了driverElement類型,調用find_element_by_id在driverElement下的子元素以id匹配目標元素。

 

 

上圖爲uiautomatorviewer對id,name,class的圖示說明。特別說明:若id、name、xpath等在當前driver或者driverElement查找的目標元素不是惟一元素,此時調用find_element_by_id(name\xpath)時,會返回查找匹配到的第一個元素。

 

 

 

(2)經過元素id查找當前頁面的多個目標元素

 
  find_elements_by_id()
 

在driver下經過id查找多個目標元素,其返回值類型爲list。此用法一般適用於當前driver下查詢listView、LinearLayout、 RelativeLayout等有相同佈局結構的Item;一樣除了driver以外,在driverElement下頁能夠跳用find_elements_by_id來匹配listView、LinearLayout、 RelativeLayout。

 
driver.find_elements_by_id("com.codoon.gps:id/tv_name")  // from webdriver.py
driver.find_element_by_id("com.codoon.gps:id/webbase_btn_share") \ 
  .find_elements_by_id("com.codoon.gps:id/ll_layout") // from driverelement.py
 

Tips: 帶有find_elements關鍵字的方法函數的返回類型都是list數據類型,只有driver與driverelement的實例化有find_element(s)等一系列方法,list類型是不能用find_element(s)方法定位數據的。在實際的項目中可能會遇到這樣的問題,只有遍歷list,取出每個element實例化對象再進行查找定位元素。

 

 

 

(3) 經過元素name查找當前頁面的一個元素

 
  find_element_by_name()
 

使用方式與find_element_by_id相同,只是把匹配條件由id變爲name。請參考find_element_by_id的調用方式

 
driver.find_element_by_name("foo")
driver.find_element_by_id("com.codoon.gps:id/tv_name").find_element_by_name("foo")


>>> return the driverElement(obj)
 

 

 

(4) 經過元素name查找當前頁面的多個目標元素

 
  find_elements_by_name()
 

使用方式與find_elements_by_id相同,只是把匹配條件由id變爲name。請參考find_elements_by_id的調用方式,注意其返回數據類型是List,並非driverElement。

 
driver.find_elements_by_name("foo")
driver.find_element_by_id("com.codoon.gps:id/tv_name").find_elements_by_name("foo")

###  return the List<driverElement>
>>> ['driverElement1', 'driverElement2', 'driverElement3', ....]
 

 

 

(5)經過元素xpath查找當前頁面的一個目標元素

 
  find_element_by_xpath()
 

關於find_element_by_xpath的調用方法與經過id、name略有不一樣,有關Xpath的相關知識點在本章節暫且不表,後續在項目實踐中如有需求再另起專題介紹。

 
driver.find_element_by_xpath("//android.widget.TextView[contains(@text, '開始')]")
driver.find_element_by_xpath("//android.widget.LinearLayout/android.widget.TextView")
 

在Appium中,xpath所需相關的lib庫並無徹底支持,因此使用方法是以上兩種(即僅支持在driver下的xpath匹配)。目前的Appium版本沒法支持driverelement下的xpath查找,如

 
driver.find_element_by_xpath("//android.widget.LinearLayout/android.widget.TextView") \ 
.find_element_by_xpath("//android.widget.TextView[contains(@text, '開始')]") // This is the Error!
 

 按上面的寫法Appium就會報錯,緣由是「.find_element_by_xpath("//android.widget.TextView[contains(@text, '開始')]")」不能在Element下查找子元素。

 

 

 

(6) 經過元素xpath查找當前頁面的多個目標元素

 
  find_elements_by_xpath()
 

 參照find_element_by_xpath的調用方式,需注意返回類型爲List,用法參考find_elements_by_name()的例子

 

 

 

(7) 經過元素class name查找當前頁面的的一個元素

 
  find_element_by_class_name()
 

在實際項目中,測試app中class name並不能作爲界面的惟一標示定位,因此在實際中幾乎沒有使用class name在driver查看元素,在driverelement下查找子元素用class name纔是正確的使用方式。

 

 

 

(8) 經過元素accessibility_id (content-desc)查找當前頁面的一個元素

 
  find_element_by_accessibility_id()
 

在uiautomatorviewer中,content-desc內容即爲accessibility_id,在selenium庫裏能夠用find_element_by_name()來匹配content-desc的內容;在Appium庫裏則用find_element_by_accessibility_id()來匹配content-desc的內容。由於Appium繼承了Selenium類,因此若是find_element_by_name沒法準肯定位時,請試試看find_element_by_accessibility_id。

 

   經常使用的獲取控件類API就是以上這些。其餘的查找和匹配的api還有find_element_by_link_text、find_elements_by_link_text、find_element_by_tag_name、find_elements_by_tag_name、find_element_by_css_selector、find_elements_by_css_selector等,用法都與上述相似。

 

 

 

3、元素操做類API

 

   咱們在實現PC端瀏覽器Webdriver自動化時,對於網頁上的目標的操做主要有:點擊(click)、 雙擊(double_click)、滾動(scroll)、輸入(send_keys),而移動端特有的輔助類api:輕擊(tap)--支持多點觸控,滑動(swipe),放大元素(pinch),縮小元素(zoom)

 

(1)點擊事件 

 
  click()
 
  tap()
 

click和tap都能實現單擊的效果。其區別在於click是做用於driverelement的實例化對象,而tap是對屏幕上的座標位置進行點擊。前者對元素的位置變化並不敏感,然後者是針對具體的像素座標點擊,受分辨率和元素位置影響較大。

 

 

 

(2)輸入事件

 
  send_keys()
 
  set_text()
 

 send_keys和set_text也都能知足輸入文本內容的操做。其區別在於send_keys會調用設備當前系統輸入法鍵盤,而set_text直接對目標元素設置文本。由此可推,send_keys的輸入內容每每和預期內容不一致,而set_text的輸入則是直接賦值,並非鍵盤事件。

 

 

 

(3)滑動(翻屏)事件

 
  swipe() 
 
  flick()
 

swipe和flick都是滑動操做,它們都是從[start_x, start_y]劃到[end_x, end_y]的過程,惟一不一樣的是swipe比flick多了一個duration參數,有了這個參數就能夠自定義從start到end動做的做用時間,以達到快速滑動或者慢速滑動的效果。

 

 

 

(4)縮放事件

 
  pinch()
 
  zoom()
 

默認會對目標元素進行放大一倍或者縮小一半的操做,此api方法適合於在測試運動地圖的縮放時的變化。

 

 

 

(5)長按事件

 
  long_press()
 

長按方法是在TouchAction類中,因此在使用時須要先import TouchAction。在刪除運動歷史記錄時,在記錄列表長按刪除,

 
action1 = TouchAction(self.driver)
driver_element = driver.find_element_by_xpath("sport_history_item_xpath")

action1.long_press(driver_element).wait(i * 1000).perform()   // i爲長按控件的時間,單位秒
 

 

 

(6)keyevent事件(android only)

 

  在Android keyevent事件中,不一樣的值表明了不一樣的含義和功能,好比手機的返回鍵:keyevent(4); 手機的HOME鍵: keyevent(3)等等,具體keyevent與對應值關係請參考http://blog.csdn.net/yun90/article/details/51036544 

 

 

 

4、元素事件類API

 

(1) reset

 
  reset()
 

用法:driver.reset(),重置應用(相似刪除應用數據),如首次登陸app時出現的引導頁,則能夠用reset來實現需求。

 

 

 

(2) is_app_installed

 
  is_app_installed()
 

檢查app是否有安裝 返回 True or False。例如:在微信登陸時,選擇登陸方式時會判斷是否已安裝微信,若未安裝則有dialog彈框,已安裝則跳轉到微信登陸頁面,

 
driver.find_element_by_id("weixin_login_button").click()
if driver.is_app_installed("weixin.apk"):
    // To do input User, Passwd
else:
    // show dialog
 

 

 

(3)install_app

 
  install_app()
 

接上個例子,若未安裝微信出現dialog彈框,檢查完dialog後再安裝微信app。特別說明:例子中的"weixin.apk"是指app_path + package_name,

 
複製代碼
複製代碼
driver.find_element_by_id("weixin_login_button").click()
if driver.is_app_installed("weixin.apk"):
    // To do input User, Passwd
else:
    check_dialog()
    driver.install_app("weixin.apk") 
複製代碼
複製代碼
 

 

 

(4) remove_app

 
  remove_app()
 

在測試老版本兼容用例時,用老版本替換新版本時,須要卸載新版本,再安裝老版本,因此須要調用到此方法,

 
driver.remove_app("new_app.apk")  # 卸載
driver.install_app("old_app.apk") # 安裝
 

 

 

(5) launch_app

 
  launch_app()
 

打開一個capabilities配置的設備應用。此方法目前並無使用。待之後用到時再來作更新。

 

 

 

(6) close_app

 
  close_app()
 

 關閉app應用程序。此方法經常使用在代碼末尾,在清理和釋放對象時使用。結合unittest框架常見tearDown()裏使用,

 
複製代碼
複製代碼
import unittest

class demo(unittest.TestCase):
    def setUp(self):
        pass
    
    def tearDown(self):
        driver.close_app()
        driver.quit()
複製代碼
複製代碼
 

 

 

(7) start_activity

 
  start_activity()
 

此方法適用於測試中需使用兩個及以上的app程序。例如,在運動相關的測試時,首先須要打開Gps模擬打點工具,開始打點。而後打開咕咚選擇運動類型開始運動,那麼能夠在啓動capabilities配置時打開Gps工具,開啓配速打點後再打開咕咚app,

 
複製代碼
複製代碼
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps={'platformName': 'Android',
                        'deviceName': 'Android Mechine',
                        'appPackage': ' Package of GpsTools',
                        'unicodeKeyboard':True,
                        'resetKeyboard':True,
                        'noReset':True,
                        'appActivity': 'activity of GpsTools'})

# TO DO Gps Mock action

driver.start_activity("com.codoon.gps", "ui.login.welcomeActivity")
複製代碼
複製代碼
 

  

 

(8) wait_activity

 
  wait_activity()
 

此方法適屬於appium等待方法的一種。不管是webdriver仍是appium,等待方法分爲三種類型:顯式等待、隱式等待,time.sleep;從wait_activity的源碼能夠看出,是屬於隱式等待。有關等待方式之後能夠另開專題詳細說明,這裏不作贅述。

 

  此方法主要使用在須要網絡加載時的等待,好比在用戶登陸做爲前提條件時,wait_activity接受三個參數: 須要等待加載的activity的名稱,timeout超時時間(秒),檢測間隔時間(秒),

 
driver.login_action()
driver.wait_activity("homepage.activity", 30, 1)
driver.find_element_by_id("個人").click()
 

其含義是,等待加載app的homepage的activity出現,等待最長時間30秒,每隔1秒檢測一次當前的activity是否等於homepage的activity。如果,則推出等待,執行點擊個人tab的action;若否,則繼續等待,30秒後提示超時拋出異常。

 

 

 

4、其餘(此類別下主要對上述沒有提到的api方法的補充)

 

(1) 截屏

 
  get_screenshot_as_file()
 

用法:driver.get_screenshot_as_file('../screenshot/foo.png'),接受參數爲保存的圖片路徑和名稱

 

 

 

(2)size 和 location

 
  size()
 
  location()
 

size 和 location是對element位置和尺寸的獲取,這兩個屬性主要運用在有可划動的控件,如完善我的資料頁,生日、身高和體重都須要划動。以前咱們提到的swipe和flick是針對設備屏幕進行划動,顯然在這裏不適用。並且沒有一個特定的方法,因此須要咱們本身針對可划動控件進行划動,

 
  swipe_control()
 

 

 

(3)獲取控件各類屬性

 
  View Code
 

用法: driver.find_element_by_id().get_attribute(name),name便是左側的標誌(class,package,checkable,checked....),返回值爲str類型,即使是true or false,可是實際上是"true" or "false"

 

 

 

 

 

(4)pull_file

 
  pull_file()
 

將設備上的文件pull到本地硬盤上,在手機號註冊時須要獲取手機驗證碼,此時的實現方式是用另外一個apk提取到驗證碼存在手機內存中,再用pull_file獲取到驗證碼內容,使得appium能夠將正確的驗證碼填入。

 

  

 

  本章節Appium經常使用的一些API函數,往後有須要會慢慢地進行補充。雖然不能面面俱到,但在實際項目中涉及到的都已經差很少提到了。當咱們對某個功能進行測試的時候,首先要對其進行操做,這個時候就要考慮到找到相應的對象元素,調用具體的事件類函數,驗證結果的時候,咱們要檢測操做產生的結果是否是與咱們預期的一致?那這就要去考慮相應的Assert函數(即斷言)了。因此記住這六字箴言:對象-事件-斷言,即可以使你能夠着手對任何一個App編寫對應的自動化測試用例了。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息