App 測試自動化: RobotFramework + Appium (3)
這篇要提該如何串接 CI 與 TCMS 系統,基本上想要實踐的想法就是,當開發者將程式碼推上 git 時,觸發 CI pipeline 流程,流程包含 build -> test -> deploy,所以只要有新的版本,都會經過自動化測試的驗證,並且將執行結果更新回到 TCMS 系統上,對 QA 來說,只要關注失敗的 Test Run 就好。
這裡用的 CI 是 gitlab CI,TCMS 是 Kiwi 雲端版。Kiwi 因為有支援 RobotFramework 以及自動化測試,然後又便宜,所以我們公司目前採用 Kiwi 作為 Test Case Management System。
概念其實很簡單,分作兩部分,第一部份怎麼將 RobotFramework 的執行結果更新到 TCMS 系統中,第二部分則是怎麼讓 CI build 同時去觸發 RobotFramework 對新 build 執行自動化測試。
先講第一部分,怎麼將 RF 的執行結果更新到 TCMS 中。
- 先安裝 RF 的 kiwitcms 套件
pip install --upgrade kiwitcms-robotframework-plugin
- 在 Home directory 中,建立 ~/.tcms.conf 檔案,並輸入你的 Kiwi 網址與帳號密碼
[tcms]
url = https://<your_tenant_name>.tenant.kiwitcms.org/xml-rpc/
username = <login_account>
password = <your_password>
3. 將底下程式 (儲存為 tcmsTools.py)跟你的 RF 腳本放在一起
import os
from zealand.listener import KiwiTCMS
from zealand.listener import RFBackendclass PrivateTenantBackend(RFBackend):
def default_tester_id(self):
user_id = self.built_in.get_variable_value('${build_user_id}')
return user_id def finish_test_run(self):
self.rpc.TestRun.add_tag(self.run_id, 'automation')class PrivateTenantKiwi(KiwiTCMS):
backend_class = CuboBackend
為什麼要加這個程式,因為我們的 Kiwi 環境是直接跟 Kiwi 租用的,所以呼叫 tcms_api 的 User api 都會得到 403 Forbidden 的錯誤,為了避開這個錯誤,我在這段程式中多加個 build_user_id
來讓你可以直接輸入 tester 的 user id,而繞開 User API 的呼叫(如果你是自己架設 Kiwi 系統,應該是可以不用多加這段程式碼)。另外,這段程式也會在結束測試時,在該 Test Run 多加個 automation
的 tag,如此一來在 Kiwi 中搜尋 automated test runs 時會比較容易。
接下來在你的 RF 腳本中,要多帶幾個參數
*** Variables ***
${plan_id} 11
${product} Cubo Ai Baby Camera
${build_user_id} 9062*** Test Cases ****
成功登入
[Tags] TC-1110 login
#.....
- plan_id: 這個 Test suite 是要測試哪個 Test plan。我的習慣是會建立一個 Automation 的 Test plan,然後在這裡指定該 Test plan 的 ID
- product: 輸入你 Kiwi 中的產品名稱
- build_user_id: 輸入 tester 的 user id (如果你不是用我附加的程式碼,請在這裡換成 tester 以及該測試者的 email)
另外在每個 Test case 中,會多帶 [Tags] TC-1110 login
,其中 TC-1110 是某個 test case 的 ID,這裡是用 Tags 的指令來表示該 test case 對應到 Kiwi 中是哪個測試項目。
執行 RobotFramework 的方式改為:
export TCMS_PRODUCT_VERSION=2.0
export TCMS_BUILD=2377
robot --listener tcmsTools.PrivateTenantKiwi tcms_test.robot
執行完畢後,檢查 Kiwi,就會有筆 Test run 被建立出來:
如此一來,RobotFramework 與 Kiwi的串連就完成了。
但是你可能有注意到,上面在執行 RobotFramework 腳本時,有多帶個 TCMS_PRODUCT_VERSION 與 TCMS_BUILD ,這兩個參數從哪裡來,其實就是要從 CI build 而來。
什麼?你們公司還沒有 CI Build? 那要先檢討一下了
我們用 gitlab CI 來做範例,我們的做法是在公司放一台 Mac mini 執行 gitlab-runner 來跑 CI。所以當工程師把 Code commit 並 push 到 gitlab 時就會觸發 CI 流程。
.ios-build-task:
stage: build
tags:
- ios-build
only:
- dev.ios-test-task:
stage: test
variables:
GIT_SUBMODULE_STRATEGY: recursive
tags:
- ios-build
only:
- devstages:
- build
- test
- deployvariables:
LC_ALL: "en_US.UTF-8"before_script:
- pod repo update
- pod installbuild_project:
extends: .ios-build-task
script:
- xcodebuild clean -workspace "Cubo.xcworkspace" -scheme "Cubo" | xcpretty
- bundle exec fastlane beta_build
artifacts:
paths:
- build.xcarchive
- buildautomation-test:
extends: .ios-test-task
script:
- export TCMS_PRODUCT_VERSION=$(bundle exec fastlane run get_version_number target:Cubo | grep Result | grep -oE '[0-9]+\\.[0-9]+\\.?[0-9]*')
- export TCMS_BUILD=$(bundle exec fastlane run get_build_number | grep Result | grep -oE '\\s[0-9]+' | grep -oE '[0-9]+')
- cd automation; robot --listener cubo_tools.CuboKiwi ios_test_cases.robotdeploy:
stage: deploy
script:
- bundle exec fastlane beta_deploy
我們是用 fastlane 來 build app,fastlane 設定如下:
default_platform(:ios)platform :ios do
def install_pods
cocoapods(
clean: true,
podfile: "Podfile",
try_repo_update_on_error: false
)
end desc "Build app, and archive in ./build.xcarchive path"
lane :beta_build do
install_pods()
xcode_select("/Applications/Xcode.app")
increment_build_number({
build_number: latest_testflight_build_number + 1
})
build_app(workspace: "Cubo.xcworkspace", scheme: "Cubo", archive_path: "./build", output_directory: "./build")
end desc "Push a new beta build to TestFlight"
lane :beta_deploy do
upload_to_testflight(
skip_waiting_for_build_processing: true
)
end
end
所以可以在 test stage 可以透過 fastlane 取得 app 版本與 build number (build number 是每次會自動遞增)。不過 fastlane 的輸出比較 fancy 會用控制碼帶上顏色,所以在設定給環境變數時,控制碼會造成跟 Kiwi server 溝通上的問題,這問題苦惱了我很久,最後還是寫出這樣很奇怪的處理方式,如果你有更好的解法請務必跟我說:
bundle exec fastlane run get_version_number target:Cubo | grep Result | grep -oE '[0-9]+\\.[0-9]+\\.?[0-9]*'
在 RF 腳本中,你會想要安裝這個剛 build 出來的 app ,你可以指定 app 或者 ipa 的檔案位置,例如在我的 Fastlane 腳本中,我將 app 的 archive 儲存在 build.xcarchive 下,所以在 RF 腳本中 app 可以直接寫死該檔案的絕對路徑,當 RF 腳本執行時,就會安裝這個新 build 出來的版本。
另外這裡有個小 trick,我們的自動化測試腳本是放在另外一個 gitlab repo 中,所以在 iOS repo 裡透過 submodule 的方式,讓 gitlab CI 也自動將另外一個 repo 也 checkout 下來 (automation 目錄下)。
所以當程式碼 push 上 gitlab 時,啟動 gitlab pipeline 會自動完成三個 stage: build, test 以及 deploy
執行完畢後,檢查 Kiwi,一樣會有筆 Test run 被建立出來:
整個設定過程你大概會面臨到很多 try and error 的機會,要設定好也不容易,但盡量是簡化設定,避免環境變動影響到自動化測試的結果,如果自動化測試三天兩頭損壞,那麼久了沒修理就慢慢失去它的意義了。