測試做爲質量保證極其重要的一環,在移動App開發流程中起到很是關鍵的做用。從開發工程師到測試工程師,人人都應具有良好的測試意識,將隱患和風險在上線以前找出並解決,能夠有效的減小線上事故。html
美團和大衆點評App做爲美團點評平臺的主要入口,支持承載着美團點評各大業務。其中美團點評境外度假業務主要包括了出境遊相關業務以及全部的境外城市站,也是美團點評很是看重和大力發展的業務線。爲了保證質量,須要進行各項測試:冒煙測試[1]、功能測試、集成測試、專項性能測試,迴歸測試[2]。其中冒煙測試和迴歸測試大多由開發本身手動執行,有較大的優化空間。一方面,測試的人力成本較高;另外一方面,在以前的測試過程當中發生過漏測等問題,這些問題在測試階段被QA發現,又會再次返工,費時費力。android
鑑於這兩部分測試用例相對穩定,不會頻繁發生較大的變化,咱們打算將其自動化,下降人力成本投入,將測試結果報表化,避免人爲疏漏形成的一系列問題。ios
[1]冒煙測試(smoke testing),就是開發人員在我的版本的軟件上執行目前的冒煙測試項目,肯定新的程序代碼不出故障。冒煙測試的對象是每個新編譯的須要正式測試的軟件版本,目的是確認軟件基本功能正常,能夠進行後續的正式測試工做。冒煙測試的執行者是版本編譯人員。 [2]迴歸測試是軟件測試的一種,旨在檢驗軟件原有功能在修改後是否保持完整。nginx
目前業界測試方案很是多,Android和iOS雙平臺的方案加起來大約有十七八種。應該如何選擇適合團隊的測試方案呢?咱們主要考慮如下幾個方面:git
其中維護成本咱們尤其看重。目前團隊的開發和測試同窗任務都比較飽和,業務處於高速發展期,無法抽出太多的時間開發/維護測試腳本,這就須要在這方面作到在投入較少時間的前提下不影響自動化測試的結果產出。常規的TDD[3]是函數級別進行測試驅動開發,一般須要在代碼級別作不少工做,須要測試團隊投入較大的開發成本。鑑於在成本方面的考慮,咱們打算使用BDD[4]來解決這個問題。主要在行爲層面進行測試投入,在代碼層級方面投入較小,用很是有辨識力的行爲進行測試。程序員
在平臺支持方面,因爲是客戶端團隊,因此咱們但願寫好的用例能夠同時跑在Android和iOS兩個平臺上,還但願用例能夠一部分進行美團和大衆點評兩個App的複用,因此須要一個能夠跨平臺的方案。github
[3]測試驅動開發(Test-driven development,縮寫爲TDD)是一種軟件開發過程當中的應用方法,倡導先寫測試程序,而後編碼實現其功能得名。測試驅動開發是戴兩頂帽子思考的開發方式:先戴上實現功能的帽子,在測試的輔助下,快速實現其功能;再戴上重構的帽子,在測試的保護下,經過去除冗餘的代碼,提升代碼質量。 [4]行爲驅動開發(Behavior-driven development,縮寫BDD)是一種敏捷軟件開發的技術。它經過用天然語言書寫非程序員可讀的測試用例擴展了測試驅動開發方法。算法
去年年末的時候咱們團隊就自動化測試方面進行了探索。發現Calabash知足BDD和跨平臺,因而進行了小範圍試用。在腳本開發和維護方面,成本確實低於函數級別的測試開發,它能夠用一種相似天然語言的方式編寫測試用例,這是一個簡單的test case示例:sql
Scenario: 首頁
Then I press "上海"
When I press view with id "city" Then I see "海外" When I press "海外" And I press view with id "start_search" When I enter "東京" into input field number 1 Then I press list item number 1 Then I see "東京" When I press "美食" ...
這個示例相信開發工程師們甚至沒寫過代碼的人也看得懂,其實就是用常規的行爲思惟模式去編寫測試用例。其中Feature、Scenario、Step是BDD的三個核心概念:ruby
可是Calabash在業內相對小衆,遇到問題就不太好解決。好比在某些三星手機上就遇到了某些控件根據ID找不到的問題,會影響UI元素的定位。在編寫自動化腳本時,元素定位的惟一性是一個看似簡單實際上會有不少坑的問題,腳本的穩定性必定程度上依賴瞭如何進行元素定位。
其次,在Android團隊想要把方案推廣到iOS平臺的時候,咱們發現了一個很大的問題:iOS接入Calabash的成本過高。Android的接入成本很低,只須要一個重簽名的apk文件就能夠了,並不依賴源碼,而iOS的接入須要依賴源碼作一些工做,這就給iOS同窗形成了不少困難。美團和大衆點評是兩個巨大的App,在源碼接入方面的工做量並不小,並且不少隱患沒法預料,就算依賴源碼接入以後,還有一個問題須要解決:iOS的ID系統。一般iOS業務開發代碼中不是經過ID來獲取頁面元素,無論是手寫佈局代碼仍是用xib佈局,開發者通常不會給界面元素加ID,因此iOS的元素大多都沒有ID,而Calabash對元素的定位主要依賴ID,這無疑讓咱們感到雪上加霜。
在Android團隊用寫好的用例進行了幾個版本的冒煙測試以後,團隊內部Android、iOS、QA的同窗坐下來一塊兒進行了方案後續的探究,最終決定放棄Calabash,繼續尋找能夠替代的方案。
在經歷過Calabash的挫折以後,咱們在選型方面更加慎重。QA同窗對Appium有必定的經驗,因而先採用了Appium方案進行兼容性測試和部分迴歸測試。在業務快速發展的過程當中,維護成本讓QA同窗愈來愈疲於應付,因而咱們又坐在一塊兒進行新方案的討論和探索。
Calabash的BDD模式是你們承認的,也是你們願意接受的,那就須要在新的方案中,繼續使用這種方式編寫維護測試用例。咱們想把Appium和Calabash二者的優點結合起來,還想把以前寫過的Calabash的測試用例無縫遷移繼續使用。
Calabash爲何可使用相似天然語言的方式編寫測試用例達到BDD的效果呢?根本緣由是由於Cucumber。
在Calabash官網中註明了他們使用了Cucumber(一種簡單的天然語言方式的BDD開源解決方案),那麼咱們可否底層使用Appium支持,上層使用Cucumber進行測試用例的開發和維護呢?
答案固然是可行的。咱們在Appium的官方示例代碼中找到了答案。Appium官方提供了與Cucumber結合使用的例子做爲參考,雖然這部分代碼已經兩年沒更新了,可是依然給咱們提供了關鍵思路。
客戶端的同窗與QA同窗進行了討論,確認了使用QA同窗目前使用的按照App進行用例拆分的方案。以前Calabash的方案有不少能夠借鑑過來,因而咱們先進行了總體結構的調整:
按照點評和美團兩個App進行用例區分,公共步驟的封裝在common_steps.rb
中。點評和美團的目錄下分別有cucumber.yml
腳本,這是用來區分Android和iOS平臺的,內容大概是這樣:
# config/cucumber.yml ##YAML Template --- ios: IDEVICENAME='ios' android: IDEVICENAME='android'
其中Android/config
和iOS/config
是Android和iOS兩個平臺的特定配置,這部分配置代碼在support
包內,是Appium啓動須要加載的配置。
平臺的區分在env.rb
中體現出來:
class AppiumWorld end if ENV['IDEVICENAME']=='android' caps = Appium.load_appium_txt file: File.expand_path("./../android/appium.txt", __FILE__), verbose: true elsif ENV['IDEVICENAME']=='ios' caps = Appium.load_appium_txt file: File.expand_path("./../ios/appium.txt", __FILE__), verbose: true else caps = Appium.load_appium_txt file: File.expand_path('./', __FILE__), verbose: true end Appium::Driver.new(caps) Appium.promote_appium_methods AppiumWorld World do AppiumWorld.new end
這樣經過cucumber -p android/ios
就能運行相應平臺的用例了,Cucumber其餘參數自行查閱,和Calabash很是類似。
徹底移除Calabash以後,全部Calabash內置的Steps就沒有了,須要從新封裝。其中Feature、Scenario、Step的概念沒有發生變化,和Calabash徹底一致。從新封裝Steps須要依賴appium_lib。爲了下降封裝成本,提供更多可用的Steps,咱們還引入了selenium-cucumber做爲輔助使用。
最後testdata.rb
是保存測試數據的文件,例如測試帳號的登陸用戶名和密碼等數據。
最終須要依賴的庫大體是這些:
gem 'appium_lib', '~> 9.4.2' gem 'rest-client', '~> 2.0.2' gem 'rspec', '~> 3.5.0' gem 'cucumber', '~> 2.4.0' gem 'rspec-expectations', '~> 3.5.0' gem 'spec', '~> 5.3.4' gem 'selenium-cucumber', '~> 3.1.5'
這樣就完成了組合方案的總體框架。
新方案造成以後,咱們的提測流程就多了一道保障:
因而每一個客戶端RD均可以愉快的點擊腳本生成測試報告,提交給QA同窗,省去了你們本地跑測試的時間,也幫助QA同窗節約了時間,不會再出現返工或者測試遺漏的狀況。
因爲底層切換到了Appium,穩定性提升了,一樣的機型再也不出現相似Calabash的不兼容問題了(根據ID沒法定位到某個元素),QA同窗在Appium的自動化道路上已經作過很多實踐,具備相關經驗。在Webview方面支持也是比較好的,相比Calabash只是多了切換Webview和Native上下文的步驟,Appium的優點徹底體現出來了。
針對Android和iOS的接入成本,也下降到了一致。Android依舊是提供apk,iOS提供重簽名的ipa包便可,無需源碼集成,這就解決了Calabash方案iOS集成成本大的問題。
公共Steps一次封裝到處可用,在跨App複用的業務上,測試代碼也幾乎能夠複用,編寫測試腳本的成本再次下降。iOS控件缺乏ID很差定位的問題也獲得瞭解決,Appium支持ID、class、name、XPath等元素定位方式,若是前三者都不可用的狀況下,使用相對複雜但幾乎萬能的XPath均可以獲得解決。
例如一個複雜的XPath:
Then I press view with xpath "//android.widget.LinearLayout[1] /android.widget.FrameLayout[1]/android.widget.LinearLayout[1] /android.widget.FrameLayout[1]/android.widget.LinearLayout[2] /android.widget.FrameLayout[1]/android.widget.ListView[1] /android.widget.LinearLayout[1]/android.widget.LinearLayout[1]"
不用擔憂這麼複雜的XPath應該怎麼寫,這實際上是最簡單的,由於能夠經過Appium-inspector抓取獲得。固然XPath的寫法有不少種,能夠選用兼容性更好的寫法。
以前在使用Calabash的時候編寫的腳本,在封裝好公共Steps以後,幾乎無縫的進行了遷移,對上層編寫測試用例的同窗來講,幾乎沒有變化,無需關心是Calabash仍是Appium,使用和原先同樣的BDD方式繼續愉快的寫用例就好。
Calabash方案時期的homepage場景(部分):
切換新方案後homepage場景(部分):
並無太大的差異。
Cucumber能夠進行報表的可視化輸出,只要在命令後面追加--format html --out reports.html --format pretty
,在執行徹底部腳本以後就能夠看到生成好的HTML格式的測試報告,也可使用JSON的格式。
集成Jenkins的方式也相對常規,只要安裝好須要的依賴就能夠。
在測試過程當中,咱們使用了公司內部的雲測機器遠程平臺:
利用遠程平臺的真機進行遠程腳本測試,測試報告示例以下:
在境外業務線客戶端進行了自動化測試實踐,目前用於固有冒煙自動化,方案先後對好比下。
Calabash方案時期境外點評固有冒煙用例耗時:
新方案境外點評固有冒煙用例耗時(相比以前Calabash方案時期的用例有所增長):
經過數據對比能夠看出,用例數量與執行耗時並非嚴格的線性關係,在用例數量擴大一倍的狀況下,耗時並不會線性的擴大一倍。
開發成本:單個用例的開發成本主要根據用例規模相關,開發一個包含7個動做的用例大概耗時30分鐘左右,其中包括了定位元素的耗時。多個用例的開發成本不止和用例規模相關,還和用例之間是否有複用的場景相關,這就牽扯到了Scenario拆分粒度的問題,下文中有提到。
目前執行用例美團+點評總耗時20分鐘左右,下降了人力成本,避免了QA同窗返工的狀況,方案新老交替無縫平滑過渡,維護成本低。這不只是咱們團隊對自動化方案的期許,也是自動化測試的價值所在。
在使用UIAutomation的時候,Android頁面滑動採起的方式是調用scroll_uiselector
方法,例如:
Then /^I scroll to view with text "([^\"]*)"$/ do |value| text = %Q("#{value}") args = scroll_uiselector("new UiSelector().textContains(#{text})") find_element :uiautomator, args end
可是這種方式存在不穩定性因素,在某些狀況下,滑動搜索UI元素很是慢(上下滑動不少次)甚至滑動屢次最後仍然搜索不到,腳本會執行失敗。在比較複雜的App上很容易出現,是總體腳本穩定性和成功率的瓶頸。若是更換爲UIAutomation2,就可使用swipe語句進行相對精準的滑動:
swipe start_x: start_x, start_y: start_y, end_x: start_x, end_y: start_y - pixel.to_i
根據撰寫本文時Appium的最新版本v1.6.5進行實踐,發現切換UIAutomation2後使用swipe滑動,對比scroll的方式成功率提升了一倍多,耗時減半,效果很是顯著。雖然其餘語句會略微受一點影響,不過總體改動幅度很小,性價比很高,並且UIAutomation2還支持對Toast的識別,總體穩定性大幅提升,建議使用UIAutomation2。
在不少狀況下,一個test case是由一個或多個Scenario組成的,不一樣的test case又會存在部分Scenario複用的狀況,明確Scenario的拆分粒度能夠幫助開發人員下降測試腳本的編寫成本,達到必定程度上的App內部複用甚至跨App複用。尤爲在多人協做的環境下,這是一個很是值得探究的問題。
目前觸發的方式是人工觸發Jenkins job,最後輸出報告。將來要作的是在特定的時期自動觸發job進行雲端自動化,觸發時期可能會參考App的開發週期時間節點。
咱們但願團隊內人人都具有良好的測試思惟,能站在測試的角度想問題,領悟測試驅動開發的意義。經過簡單的方式讓團隊內的同窗們參與測試,體會測試,寫出更優秀的代碼。
立成,美團點評酒旅境外度假研發組Android高級開發工程師,在Android開發、跨平臺開發、移動端測試等領域有必定的實踐經驗,熱愛新技術並願意付諸實踐,致力於產出高質量代碼。
酒旅境外度假研發組,負責美團點評境外度假業務。美團點評海外站覆蓋全球100多個國家地區,收錄美食、購物、酒店、景點等各種海外商戶超過500萬家,爲出國遊玩用戶提供吃、玩、住、買、交通一站式解決方案。咱們的使命是作「最好用的境外中文消費指南」,全方位解決用戶海外旅行中的問題,最終成爲出境遊行業技術領域智能化、國際化的標杆!咱們團隊長期招聘Android、iOS、FE、Java、算法等技術方向的工程師,誠摯歡迎投遞簡歷至hongguangyan#meituan.com。
【思考題】 本文爲你們介紹的新型客戶端自動化測試方案大大下降了自動化測試的成本,可是依然存在測試腳本的迭代與維護的問題。那麼應該在什麼時間節點或者時間段對腳本進行維護,才能保證在測試過程當中不會由於腳本滯後而致使測試失敗?如何將這部分紅本降到最低?如何實現人人都是測試工程師的願景?