Designing Test Architecture and Framework
淺談軟體測試的階段與策略 提到過去因為需要自動化 Regression Test,然後設計、開發 Test Framework / Architecture 的經驗。最近也有人在問我怎麼做這件事情,重新整理一下這段經歷的分享,補充了一些資料。
Designing Test Architecture and Framework
單一的自動化測試難度不高,但是如果大量且要能夠團隊合作的 Test Architecture / Framework 複雜度就很高,我當時設計的 Test Framework 考慮以下面向:
角色 (Roles)
定義 SQA 團隊裡有哪一些角色:
Tester
:負責手動釐清、驗證問題,確認問題的程序Automation Developer
:- 寫 Test Case 的人,負責這個 Test Case 本身的設計、開發、與測試
- 也可以是 QA / QE
Automation Runner
: 跑大量 Test Case 的人- 架構部署與環境維護
- 測試環境準備、資源分配、準備 Config
- 負責每天跑大量的測試,通常是晚上跑,稱為
overnight
- 負責調整 overnight 所需要的配置與資源。
- Review 報表
SDET
: 開發、維護 Test Framework and Test Libraries 的人- 架構設計與開發
- Framework 開發與測試
- 共用 Library 開發
- 報表產生器
- 資源管理
- 環境建置
實務上,因為資源的限制或者現場的狀況, Tester / QA / QE 可能是同一個人,Runner / SDET 是同一個人。
測試架構 - SDET
底下這張圖是當時在自己家裡的白板手繪的概念圖,現在看起來有些東西表達詞不達意,但是概念是可行的 XD
圖中概念說明:
Box
:待測產品,那時候測的是 Firewall 產品的 FirmwareLabPC
:執行測試程式的機器Backend
: 產品本身需要跟很多 Backend 整合才能用,像是 DB2、MQ、WAS (Websphere Application Server)SMGR
: 負責管理、分配測試資源的節點
測試程式的開發與測試 - Automation Developer
- 單一 Test case 的開發流程與流程控制: tester 寫 test case 如何在自己的環境開發與測試
- Test Suite 的管理與結構: 如何跑整個 test suites,test suites 本身的設定檔
- 如何 Debug 自己開發出來的測試程式?然後如何整合到每天要跑的環境?
- 模擬程式的設計:有些測試程式需要製造一些特殊條件,像是 disk 滿了、CPU 80%、memory 沒了之類的 …
- 我設計由 Framework 提供這些功能,tester 只要透過參數就可以達到想要的功能即可。
部署與環境 - Automation Runner
每次跑大量測試之前,都要先 Allocate 對應資源,確認環境是否乾淨。
- 環境建置準備:
- 把環境弄到最乾淨,以 AWS 來說就是起一個乾淨的 Instance
- 用 Container 相關技術,像是 Docker-Compose、K8s …
- 測試資料準備:
- 每個 test case 都會有個別的測試資料,用來製造測試情境
- 測試資料的分類
- 待測程式的部署或者安裝:
- 這些東西統稱
artifacts
, 建議包含以下資訊:Version Number, Change ID (hash code, serial no), BuildID (通常是時間, 像是 YYYYmmDD-HHMM), branch … - 從 build machine or S3 抓下最新的 build,安裝好後,把 test case 需要用的設定檔設定好
- 這些東西統稱
相關參閱:
每天晚上跑大量的測試 - Automation Runner
測試程式一多,就需要管理、跑的時候要有彈性,所以 Test Runner 的設計有以下要考慮:
- 跑單一 testcase, 跟跑數個 suites 的設定檔, 然後可以個別指定設定檔, 或者 overwrite 每個 testcase 的設定檔
- 測試排程控制 (分散式):
- 如何同時跑多個 test case?
- 排隊或者平行?
- test case runtime 在哪一台機器跑?
- 如果 test case 跑太久怎麼辦?這裡我設計了
duration
機制,也就是 tester 必須指定每個 test case 最長的執行時間,超過 test runner 就會把 thread 砍掉,並且執行 cleanup,把環境還原,把測試標記失敗。
- 額外的測試條件 Callback: 跑大量 test suite 時,可以同時跑其他的東西製造測試情境
- 測試結果的 Log 與報表
- Log 分成給 tester 看得、Framework Library Design 看的,還有 Framework Developer 看得。
- 每個 testcase 都有 owner, 報表每天會自動寄給 owner
- Rerun 機制
- 每次跑大量的 test suites 產生報表的同時,會同時產生另一個 runner 的設定檔,只要 reviewer 看過覺得需要重跑,按下 rerun 就可以自動化重跑
- 資源監視與管理
- 待側機器的資源狀況,主要有 CPU / Memory / Disk 狀況
- 哪一些資源現在已經被使用,可能是人、也可能是被機器要走了
Test “Test Framework” - SDET
整個 Test Framework 自己的 Unit Test 以及 Libraries 都是透過自己測自己的方式實作,也就是自己的 Libraries 也會產生測試報表,每次加功能之前,都會用自己測自己 (當時我還不知道那叫 TDD)。
這樣的想法是以前學 Java 時,聽學校老師說 Java Compiler 用什麼寫?當然是用 Java 寫囉!當時還不懂,後來就懂了。
Dynamic Config - SDET
為了讓測試流程更有彈性,所以參考物件導向的概念,設計了類似繼承、Annotiation 概念的配置檔,這也是整個 Framework 的核心架構,相關設計隨筆參考:Talk about compiler and parser
老人談當年勇
下面是以前我設計 Test Framework for Regression 時規劃的流程與設計 (System Level Design),摘錄一些當時簡報的圖檔與心得。
這一整套 Test Framework 是設計給一個團隊使用,裡面包含了協作、資源系統、報告、教育訓練、完整的文件手冊、範例程式碼、設計文件 … 等,當時一直想把他商品化,可惜並沒有機會。 (老了,要開始提當年勇了 XD)
Workflow / Architecture
這張圖是大的測試流程圖,包含準備、自動更新 Firmware、Sequence / Parallel 的 Test Case 執行程序、以及 Log and Report。
說明如下:
- 橘色:準備工作,確認待測項目與資源是否足夠。這裡有一段演算法是要先計算待測 Suites 總共需要哪一些資源,然後跟 Resource Management 詢問現在有多少資源,能否執行。
- 藍色:待測目標,可以想像成部署概念,也就是測試都會自動重新部署帶測版本,這也就是 導入 CI/CD 的第一步 提到的概念。
- 紅色:各個不同的 Compoments 的測試案例集合 (Test Suites),執行方式有循序 (Sequence) 或者平行 (Parallel)
- 綠色:執行結果產生報表,包含每個測試的執行資訊、負責人、Log,Rerun 的方式等。
Test Case Management
Test Cases / Test Suites 的目錄結構設計,參考 Java package 概念。而且 Suites 和 Test case 的設定檔具有繼承、annotation、branch 概念。branch 概念就是說屬於特定版本的設定,可以建立新的 設定檔,附加版本號碼,Framework 只要找到這樣的檔案,就會自動 overwrite 相關設定。
核心概念有兩個:
- Testcase 的 Config Management:有 Global、Suite Level、Testcase Level、Version Level 四個層級,這四個層級是繼承架構
- Testcase 的 Package Management:類似於 Java Package 的設計,執行 Runner 支援 wildcard 指定特地的 Package 全部,或者 exclude 特定的 Testcases.
- 類似 Branch 的概念,在 Ansible 裡也有。
- 這裡我實作了一個簡單的 parser,parse 每個 testcase 設定檔的相關需求,包含繼承、annotation、branch 等概念,實作內容包含基本的 syntax check、abstract structure tree (AST) 等,如果 syntax error 會吐出 error code, 同時指出哪一行錯誤。最後在 runtime 變成一個 data model 給 test runner 使用。在 Talk about compiler and parser 有簡單的描述。
Test Case 標準程序
每一個 Test Case 都有這樣的標準程序,分成五個:
Pre-Procedure
: 由 Framework 控制,通常是環境檢查,像是檢查 Config 合法性、 HTTP / Storage Server 等共用資源Setup
: 測試準備工作,通常是初始化資料,由 Tester 自行設計Test
: 主要的測試程序在這裡Cleanup
: 清理測試資料與環境,由 Tester 自行設計Post-Procedure
: 由 Framework 控制,自動處理後續不必要的程序,或者是從待測目標下載所有 Log / backtrace。
從上述中提及分成 Framework Level 和 User Level:
- Framework Level 根產品的特殊性有關係,產品相關的共用程序都封裝在 Framework 層,這層由 SDET 負責
- User Level 則是給 SQA 開發 Test Case 使用。
中間有一些 function,像是 Raise CPU, Memory Up,是由 Framework 控制。Tester 在開發 Test Case 時,只要透過開關開啟就可以了。
Test Case Lifecycle Controller
每個 Testcase 都有自己的 Config,有一些生命週期有關的設定,像是:
- 每個 Testcase 再跑時,只能跑多久?
- 每個 Testcase 是否有特殊需求?例如只能跑在哪一些硬體機型?
- 如果失敗了要重跑?
執行報表
這是執行後給 Testcase owner 的測試報告,列出 owner 每個 test case 的執行結果與 Log.
這個報表內容主要是給負責 Testcase 的人,包含跑在哪一個環境、測試的 版本資訊
、相關的 Testsuites / Testcases 、每個測試執行的時間、跑在哪、成功率、Log … 等。
資源管理 (Admin Console)
這個 Framework 是分散式架構,所有很多機器要管 (大概兩櫃) 的機器要管理,測試時必須要去配製這些資源。這張圖是測試資源的管理,Framework 會依據資源狀況,自動分配 Job。用 ZK 實作的。
這個 Console 呈現這些資訊:
- 每台機器是誰在使用:團隊很多人,所以避免資源競爭。
- 待測資源資訊:包含 FW 版本、CPU、Memory、IP … 等
- 執行測試 Node 資訊:包含 FW 版本、CPU、Memory、IP、OS … 等
- Build: 每天自動從米國 Mirror 回來的 Artifacts
我在 軟體自動化測試常見的問題 中問題到的描述,就是這段實作過程的經歷。
實作技術
整套系統大概使用以下技術實作:
- Server: RedHat (RHEL), Ubuntu, Windows Server 2003
- Programming Language: Java, Python (jython), Bash,
- Auto Test Infrastructure: STAF, STAX
- ZK: Web Framework
- Database: MySQL
結論
這個架構的設計包含以下概念:
訊息佇列 (Message Queue)
:儲存工作進度與佇列工作流程 (Workflow)
: 主要的流程控制器、輸出輸入處理、異常處理、執行單元 (Testcase Runner) … 等批次工作 (BatchJob)
:負責執行運算的運算單元。資源分配策略
: 為了讓資源更有效地利用,所需要的資源分配策略。
這段設計,算是我個人成長最多的時間,也是思考最多的架構設計的,即使已經十年了,還是記憶深刻。
延伸閱讀 (站內)
- 淺談軟體測試的階段與策略
- 需求管理 (Requirement Management)
- 軟體自動化測試常見的問題
- Software QA 的職能條件
- 三種 QA
- 協同合作系統建制與導入 - 以 Redmine 為例
- Version Control
- Resource Provisioning and DevOps
- Software Development Lifecycle
- 從 iOS 無限黑屏事件,淺談軟體測試階段 - 回歸測試 Regression Test
- Artifacts Management
- 分散式系統設計 - 正體中文版翻譯記事