2016年1月18日 星期一

Testing: 測試自動化(三): 實作與Demo

介紹完Cucumber與Calabash的基本認識與流程,這個章節則進入尾聲,也就是實際看看該如何從安裝、撰寫測試案例到運行。這個章節共分為環境安裝、撰寫測試案例、執行並產生測試報告與Demo。(以下的測試是以Android應用程式為範例,然而Calabash也可以支援IOS,該領域的測試自動化流程可以參考[Calabash-IOS](https://github.com/calabash/calabash-ios)的相關教學,在此不多做說明。)

# 環境安裝
首先是環境安裝,先前的章節有提到Calabash是基於Ruby on Rails,想當然爾我們需要安裝Ruby。以下為Windows環境,Mac環境請參考Ruby on Rails實戰聖經Calabash-android的教學。

1. Rubuy Installer
    - 下載RubyInstaller
    - 安裝過程
        - 勾選名為"Add Ruby executables to your PATH"的選項
        - 測試
            - 開啟Command Line Window,並輸入"ruby -v"來測試
            - 若顯示"ruby 2.0.0p353 (2013-11-22) [x64-mingw32]"則是成功安裝

2. DevKit
    - 下載DevLit:
    - 下載至你欲儲存的儲存位置,如: D:\DevKit
    - 開啟Command Line Window,導航至你儲存DevKit的路徑,並輸入"ruby de.rb init"。
    - 檢查名為"config.yml"的檔案是否存在
    - 在Command Line Window下輸入"ruby dk.rb install"。
    - 待安裝完成

3. Rails及Calabash-Android
    - 開啟Command Line Window
        - 輸入"gem update --system"
    - 安裝Rails
        - 輸入"gem install rails --no-ri --no-rdoc"
    - 測試
        - 輸入"rails –v"
        - 若顯示"Rails 4.0.2"則是成功安裝      
    - 安裝Calabash-android
        - 開啟Command Line Window,輸入"gem install calabash-android"
        - 待安裝完成


# 撰寫測試案例
待安裝環境後,接下來該如何利用Cucumber來撰寫測試案例?這邊分為三個步驟: 產生Cucumber Skeleton、撰寫測試案例與情境、實作Ruby程式:

## 1. 產生Cucumber Skeleton

產生Cucumber Skeleton的目的是,我們需要產生一個名為"featrues"的資料夾,當中會存放測試相關的內容,主要包含了測試案例(*.feature)及Ruby執行的檔案(*.rb),可以讓開發者或測試工程師存放自己撰寫的內容。我們可以開啟Command Line Window,使用"calabash-android gen"的指令來產生Cucumber Skeleton,其結構如下圖所示:

428343_08

## 2. 撰寫測試案例與情境

在建立Cucumber Skeleton後,我們可以在Cucumber Skeleton的資料夾中建立即將測試的檔案,下圖為實際的測試案例,測試目標為"Android應用程式- friDay購物"的內容,分為欲測試的功能與情境描述,下列皆以該案例陳述。

428343_09


    - 測試功能: 包含目的與測試角色。
        1. 目的: 測試使用者使用該應用程式時,可以順利從首頁瀏覽商品,並且選擇一件商品。
        2. 測試角色: friDay購物的會員(需申請一個已知的帳號進行測試,並且成功驗證註冊信後成為friDay購物的會員之一。) 
        
    - 情境描述: 可區分為情境描述與步驟。
        1. 情境描述: 使用者可以從首頁Viewpager的GridView內容選擇一個商品。
        2. 步驟: 步驟的描述可以包含三大元素: Given、When與Then、另外兩個非必要元素: And和But。
            - Given: 描述測試的前置條件,以上圖為例: 使用者需直接關閉使用者導覽進入首頁。
            - When: 描述關鍵的行為或判斷的觸發行為,以上圖為例: 當使用者登入時,需做後續的三個步驟。
            - Then: 描述預期的結果或是斷言,類似Unit Test的斷言,你預期會有甚麼樣的行為產生,以上圖為例: Then I enter "商品資訊" page.,使用者則會進入商品資訊頁面。
            - And和But: 當有多個Given、When或是Then的時後併用,如同自然語言的"以及..."和"但是..."。

## 3. 實作Ruby程式

在建立撰寫測試案例與情境後,便是我們將欲測試的步驟給實現出來的時候,而除了Ruby本身的語法結構外,實際上我們也需要Calabash-android提供的API讓我們達成測試的實作。以下為基本的操作API:
    
    - Query(uiquery, *args): 找出可視範圍的View(視圖)。我們可以透過該API找出手機可視範圍的View,以及應用程是物件,讓測試者可以斷言結果或是從中得到相關資訊,其回傳結果會為一個陣列。以下圖為例: 下圖則是想找出與變數"pageName"相同文字內容的textView物件,回傳結果如下所示。

428343_10

回傳結果: 
[{"class"=>"android.widget.TextView", "tag"=>nil, "description"=>"android.widget.TextView{3d05290a V.ED.... ........ 408,28-672,116}", "id"=>nil, "text"=>"商品資訊", "visible"=>true, "rect"=>{"height"=>88, "width"=>264, "y"=>103, "x"=>408, "center_x"=>540, "center_y"=>147}, "enabled"=>true, "contentDescription"=>nil}]

    - touch(uiquery, options={}): 在測試的過程中,操作上往往我們會運用點擊的事件,該如何在Calabash-android中模擬點擊?便是使用touch這個API。我們可以透過touch API中的第一個參數,先查詢所需點擊的UI物件,便可完成欲點擊的物件行為。以下圖為例: 下圖是以查詢符合變數"buttonName"所帶之文字內容的物件,若該物件存在,則點擊它。 

428343_11

    - enter_text(uiquery, text, options={}): 輸入文字也是常用的操作行為,有時測試人員常需要進行文字輸入,對某些欄位輸入特定字串,可以使用該API。以下圖為例: 下圖是在在Webview內的"account"欄位與"password"欄位輸入帳密。

428343_12

    - tap_when_element_exists(uiquery, options={}): tap_when_element_exists API與touch類似,該API可以在點擊之前等待該物件出現,在該誤鍵出現後才進行操作。 

428343_13

    - scroll_down and scroll_up: 滑動捲軸也是常用的事件之一,當一個可視範圍超出螢幕時,便可使用該操作,如下圖所示。

428343_14

# 執行並產生測試報告
當上述步驟都完成後,則進入最後的階段 - 執行。我們可以開啟Command Line Window,導航至Cucumber Skeleton產生的features內的同一層目錄中,並將測試的APK放至其內,接著輸入"calabash-android run apkName.apk –format html –out reports.html" ,便可產生測試報告。該指令是讓測試者可以運行欲測試的APK後,產生reports.html這個檔案作為輸出內容,測試者則可以利用這份檔案對測試案例的成功與否進行檢視。

428343_15

# Demo
上述步驟皆完成,也表示我們順利完成一個Android應用程式的自動化測試流程,本篇的分享也告一段落,但在此有些建議,我們應該要釐清測試目的為何?如果開發者或是測試人員僅是將操作流程自動化,其實這樣的測試與[Monkey Test](http://developer.android.com/intl/zh-tw/tools/help/monkey.html)類似,既然我們需要透過測試案例的方式來確認我們的功能是否運行正常,就並非只是僅僅將操作透過自動化方式來實現,而是在每個測試案例的操作行為上,去斷言這些操作行為後,測試人員將預期的結果為何?這樣最後的測試報告所賦予的實質意義才會遠比僅僅將每個操作流程自動化來得大,我們也可以確實收斂和釐清每個測試環節失敗的原因為何。最後就讓我們來看看實際的運行結果,以下影片則記錄該測試案例的運行過程。