從0到1搭建移動App功能自動化測試平台(3):編寫iOS自動化測試腳本

通過前面三篇文章,我們已經將iOS自動化功能測試的開發環境全部準備就緒,也學習了iOS UI控制項交互操作的一般性方法,接下來,就可以開始編寫自動化測試腳本了。

在本文中,我將在M項目中挑選一個功能點,對其編寫自動化測試腳本,演示編寫自動化測試用例的整個流程。

語言的選擇:Python or Ruby?

之前介紹Appium的時候也提到,Appium採用Client-Server的架構設計,並採用標準的HTTP通信協議;Client端基本上可以採用任意主流編程語言編寫測試用例,包括但不限於C#、Ruby、Objective-C、Java、node.js、Python、PHP。

因此,在開始編寫自動化測試腳本之前,首先需要選定一門編程語言。

這個選擇因人而異,並不涉及到太大的優劣之分,基本上在上述幾門語言中選擇自己最熟悉的就好。

但對我而言,選擇卻沒有那麼乾脆,前段時間在Python和Ruby之間猶豫了很久,經過艱難的決定,最終選擇了Ruby。為什麼不考慮Java?不熟是一方面,另一方面是覺得採用編譯型語言寫測試用例總感覺太重,這活兒還是解釋型語言來做更合適些。

其實,最開始本來是想選擇Python的,因為Python在軟體測試領域比Ruby應用得更廣,至少在國內,不管是公司團隊,還是測試人員群體,使用Python的會比使用Ruby的多很多。

那為什麼還是選擇了Ruby呢?

我主要是基於如下幾點考慮的:

  • 從Appium的官方文檔來看,Appium對Ruby的支持力度,或者說是偏愛程度,貌似會更大些;在Appium Client Libraries列表中將Ruby排在第一位就不說了,在Appium Tutorials中示例語言就只採用了Ruby和Java進行描述。
  • Appium_Console是採用Ruby編寫的,在Console中執行的命令基本上可直接用在Ruby腳本中。
  • 後續打算引入BDD(行為驅動開發)的測試模式,而不管是cucumber還是RSpec,都是採用Ruby開發的。

當然,還有最最重要的一點,身處於珠江三角洲最大的Ruby陣營,周圍Ruby大牛雲集,公司的好多業務系統也都是採用Rails作為後台語言,完全沒理由不選擇Ruby啊。

第一個測試用例:系統登錄

在測試領域中,系統登錄這個功能點的地位,堪比軟體開發中的Hello World,因此第一個測試用例就毫無懸念地選擇系統登錄了。

在編寫自動化測試腳本之前,我們首先需要清楚用例執行的路徑,路徑中操作涉及到的控制項,以及被操作控制項的屬性信息。

對於本次演示的APP來說,登錄時需要先進入【My Account】頁面,然後點擊【Login】進入登錄頁面,接著在登錄頁面中輸入賬號密碼後再點擊【Login】按鈕,完成登錄操作。

確定了操作路徑以後,就可以在Appium Ruby Console中依次操作一遍,目的是確保代碼能正確地對控制項進行操作。

第一步要點擊【My Account】按鈕,因此先查看下Button控制項屬性。要是不確定目標控制項的類型,可以直接執行page命令,然後在返回結果中根據控制項名稱進行查找。

[1] pry(main)> page :buttonn...(略)nUIAButtonn name, label: My Accountn id: My Account => My Accountnniln

通過返回結果,可以看到【My Account】按鈕的name、label屬性就是「My Account」,因此可以通過button_exact(My Account)方式來定位控制項,並進行點擊操作。

[2] pry(main)> button_exact(My Account).clicknniln

執行命令後,觀察iOS模擬器中APP的響應情況,看是否成功進入「My Account」頁面。

第二步也是類似的,操作代碼如下:

[3] pry(main)> button_exact(Login).clicknniln

進入到登錄頁面後,再次查看頁面中的控制項信息:

[4] pry(main)> pagen...(略)nUIATextFieldn value: Email Addressn id: Email Address => Email AddressnUIASecureTextFieldn value: Password (6-16 characters)n id: Password (6-16 characters) => Password (6-16 characters)nUIAButtonn name, label: Loginn id: Log In => Loginn 登錄 => Loginn...(略)n

第三步需要填寫賬號密碼,賬號密碼的控制項屬性分別是UIATextField和UIASecureTextField。由於這兩個控制項的類型在登錄頁面都是唯一的,因此可以採用控制項的類型來進行定位,然後進行輸入操作,代碼如下:

[5] pry(main)> tag(UIATextField).type leo.lee@dji.comn""n[6] pry(main)> tag(UIASecureTextField).type 123456n""n

執行完輸入命令後,在iOS模擬器中可以看到賬號密碼輸入框都成功輸入了內容。

最後第四步點擊【Login】按鈕,操作上和第二步完全一致。

[7] pry(main)> button_exact(Login).clicknniln

執行完以上四個步驟後,在iOS模擬器中看到成功完成賬號登錄操作,這說明我們的執行命令沒有問題,可以用於編寫自動化測試代碼。整合起來,測試腳本就是下面這樣。

button_exact(My Account).clicknbutton_exact(Login).clickntag(UIATextField).type leo.lee@dji.comntag(UIASecureTextField).type 12345678nbutton_exact(Login).clickn

將以上腳本保存為login.rb文件。

但當我們直接運行login.rb文件時,並不能運行成功。原因很簡單,腳本中的button_exact、tag這些方法並沒有定義,我們在文件中也沒有引入相關庫文件。

在上一篇文章中有介紹過,通過arc啟動虛擬機時,會從appium.txt中讀取虛擬機的配置信息。類似的,我們在腳本中執行自動化測試時,也會載入虛擬機,因此同樣需要在腳本中指定虛擬機的配置信息,並初始化Appium Driver的實例。

初始化代碼可以通過Appium Inspector生成,基本上為固定模式,我們暫時不用深究。

添加初始化部分的代碼後,測試腳本如下所示。

require rubygemsnrequire appium_libnncapabilities = {ntappium-version => 1.0,ntplatformName => iOS,ntplatformVersion => 9.3,n}nserver_url = "http://0.0.0.0:4723/wd/hub"nAppium::Driver.new(caps: capabilities).start_drivernAppium.promote_appium_methods Objectnn# testcase: loginnbutton_exact(My Account).clicknbutton_exact(Login).clickntag(UIATextField).type leo.lee@dji.comntag(UIASecureTextField).type 123456nbutton_exact(Login).clicknndriver_quitn

優化測試腳本:加入等待機制

如上測試腳本編寫好後,在Terminal中運行ruby login.rb,就可以執行腳本了。

運行命令後,會看到iOS虛擬機成功啟動,接著App成功進行載入,然後自動按照前面設計的路徑,執行系統登錄流程。

但是,在實際操作過程中,發現有時候運行腳本時會出現找不到控制項的異常,異常信息如下所示:

? ruby login.rbn/Library/Ruby/Gems/2.0.0/gems/appium_lib-8.0.2/lib/appium_lib/common/helper.rb:218:in `_no_such_element: An element could not be located on the page using the given search parameters. (Selenium::WebDriver::Error::NoSuchElementError)ntfrom /Library/Ruby/Gems/2.0.0/gems/appium_lib-8.0.2/lib/appium_lib/ios/helper.rb:578:in `ele_by_jsonntfrom /Library/Ruby/Gems/2.0.0/gems/appium_lib-8.0.2/lib/appium_lib/ios/helper.rb:367:in `ele_by_json_visible_exactntfrom /Library/Ruby/Gems/2.0.0/gems/appium_lib-8.0.2/lib/appium_lib/ios/element/button.rb:41:in `button_exactntfrom /Library/Ruby/Gems/2.0.0/gems/appium_lib-8.0.2/lib/appium_lib/driver.rb:226:in `rescue in block (4 levels) in promote_appium_methodsntfrom /Library/Ruby/Gems/2.0.0/gems/appium_lib-8.0.2/lib/appium_lib/driver.rb:217:in `block (4 levels) in promote_appium_methodsntfrom login.rb:28:in `<main>n

更奇怪的是,這個異常並不是穩定出現的,有時候能正常運行整個用例,但有時在某個步驟就會拋出找不到控制項的異常。這是什麼原因呢?為什麼在Appium Ruby Console中單步操作時就不會出現這個問題,但是在執行腳本的時候就會偶爾出現異常呢?

原來,在我們之前的腳本中,兩條命令之間並沒有間隔時間,有可能前一條命令執行完後,模擬器中的應用還沒有完成下一個頁面的載入,下一條命令就又開始查找控制項,然後由於找不到控制項就拋出異常了。

這也是為什麼我們在Appium Ruby Console中沒有出現這樣的問題。因為手工輸入命令多少會有一些耗時,輸入兩條命令的間隔時間足夠虛擬機中的APP完成下一頁面的載入了。

那針對這種情況,我們要怎麼修改測試腳本呢?難道要在每一行代碼之間都添加休眠(sleep)函數么?

也不用這麼麻煩,針對這類情況,ruby_lib實現了wait機制。將執行命令放入到wait{}中後,執行腳本時就會等待該命令執行完成後再去執行下一條命令。當然,等待也不是無休止的,如果等待30秒後還是沒有執行完,仍然會拋出異常。

登錄流程的測試腳本修改後如下所示(已省略初始化部分的代碼):

wait { button_exact(My Account).click }nwait { button_exact(Login).click }nwait { tag(UIATextField).type leo.lee@dji.com }nwait { tag(UIASecureTextField).type 123456 }nwait { button_exact(Login).click }n

對腳本添加wait機制後,之前出現的找不到控制項的異常就不再出現了。

優化測試腳本:加入結果檢測機制

然而,現在腳本仍然不夠完善。

我們在Appium Ruby Console中手工執行命令後,都是由人工肉眼確認虛擬機中APP是否成功進入下一個頁面,或者返回結果是否正確。

但是在執行自動化測試腳本時,我們不可能一直去盯著模擬器。因此,我們還需要在腳本中加入結果檢測機制,通過腳本實現結果正確性的檢測。

具體怎麼做呢?

原理也很簡單,只需要在下一個頁面中,尋找一個在前一個頁面中沒有的控制項。

例如,由A頁面跳轉至B頁面,在B頁面中會存在「Welcome」的文本控制項,但是在A頁面中是沒有這個「Welcome」文本控制項的;那麼,我們就可以在腳本中的跳轉頁面語句之後,加入一條檢測「Welcome」文本控制項的語句;後續在執行測試腳本的時候,如果頁面跳轉失敗,就會因為找不到控制項而拋出異常,我們也能通過這個異常知道測試執行失敗了。

當然,對下一頁面中的控制項進行檢測時同樣需要加入等待機制的。

登錄流程的測試腳本修改後如下所示(已省略初始化部分的代碼):

wait { button_exact(My Account).click }nwait { text_exact System Settings }nnwait { button_exact(Login).click }nwait { button_exact Forget password? }nnwait { tag(UIATextField).type leo.lee@dji.com }nwait { tag(UIASecureTextField).type 12345678 }nwait { button_exact(Login).click }nwait { text_exact My Message }n

至此,系統登錄流程的自動化測試腳本我們就編寫完成了。

To be continued …

在本文中,我們通過系統登錄這一典型功能點,演示了編寫自動化測試用例的整個流程。

在下一篇文章中,我們還會對自動化測試腳本的結構進行進一步優化,並實現測試代碼工程化。

Read More ...

公眾號:DebugTalk

原文鏈接:debugtalk.com/post/buil

相關文章

  • 《從0到1搭建移動App功能自動化測試平台(0)背景介紹和平台規劃》
  • 《從0到1搭建移動App功能自動化測試平台(1)模擬器中運行iOS應用》
  • 《從0到1搭建移動App功能自動化測試平台(2)操作iOS應用的控制項》

推薦閱讀:

通過修改User-Agent標識將PhantomJS偽裝成Chrome瀏覽器
如何搭環境
Python實踐3-Tenacity提高自動測試健壯性
selenium自動化測試入門 python unittest單元測試框架

TAG:测试开发 | 自动化测试 | iOS |