Stages in Software Testing


這幾年 DevOps 盛行,大家都在討論,然後都在喊要 CI 、要自動化測試 ….

我從 Software Developer, SQA, System Operation / Administrator 三種角色 / 職務都走過,做了幾年的 System Operation / Administrator 之後,最近開始有機會回到 Developer 身份,專注 Micro Service 與架構,反思測試的重要性感覺又更深刻。

How to be an SQA? 有過去經驗的分享。

整理一下過去做 SQA Manager 時的 Test Strategies (測試執行策略) 與心得。

名詞定義

先整理名詞定義:

  • Test Stages: 測試的階段性
    • 怎樣的測試階段,每的階段的目的性、範圍、確認點都不一樣。
    • 這些 Stage 有些事有相異性的,有些依照不同的產業、產品性質,則是屬於選擇性的。
    • Stage 種類很多,我的定義主要來自於 IBM 的測試方法。
  • Test Strategies: 策略
    • 依據不同產品特性,選擇不同 Stage 的組合,稱為策略 (Strategy)
    • 我心裡有一個基本款的策略,也就是不管是怎樣的產品,都要走完,否則就是不及格。
    • 最基本的 Test Strategy: Functional Test + Regression Test

我定義的測試全部都是黑箱,也就是不包含 Unit Test,因為那是 Developer 的責任。

摘要 Stages

有些名詞我是沿用 IBM 的體制,大概就是 xVF 之類的稱呼,只是定義是我自己的經驗匯集。

Unit Test

  • Developer 的職責,白箱測試。
  • 邊界驗證 (Boundary Test)

Functional Verification Test (FVT)

  • 功能測試,也就是主要的商業流程
  • 包含完整的 User Stories, Scenario, Use Cases
  • 這段落的測試 完成率 必須 100%, 通過率 必須 90% 以上,才能繼續往下走。
  • 完成率 以及 通過率 的比例與設定,因產品性質不同而有所不同。
  • FVT 測試環境的 Provisioning:
    • 環境建置專注在功能面 / 應用層,不是系統面
    • 不用考量 Performance 部分,像是 HA / Failover / Reliability 等,也不用去弄 DB HA / Replication
    • 測試環境要最小化,盡量使用 Container 技術,讓每個人 (Developer / QA) 都可以快速建立自己的環境。

System Verification Test (SVT)

  • 針對系統性的驗證,兩個異質性系統的溝通、配置、效能等問題。
  • 外在條件的影響,例如不同的瀏覽器、作業系統、版本、 … 等
  • 偏重在技術端、系統面的邏輯正確性與系統串接功能正確
  • 環境的建置考量:
    • 要考慮完整的系統架構,包含 HA / Failover / Reliability / DB HA
    • 要確認這些系統環境彼此的 config / functional 正常能正常運作
    • 系統之間的設定問題,要在這階段找出來。
  • 上線後的監控指標 (Metrics):系統上線後需要監控哪一些指標,要在這個階段找出來。更多參閱: 淺談系統監控與 CloudWatch 的應用

Integration Test

  • 針對不同產品元件組成的驗證
  • 著重在 商務領域 的適用性,也就是走的是 User Scenario,必須包含 商業邏輯 + 場景條件
  • 有些產業會把 System 和 Integration 合在一起稱為 SIT,我覺得不太適合。
  • End to End 可以說是一種 Integration Test
  • 環境建置考量:同 FVT 需求

Regression Test (RT)

  • 回歸測試
  • 把舊的功能全部都測過,白話文:FVT + SVT 再跑一次,包含 以前全部的 Bug
  • 測試曾經出現過的 嚴重 Bug
  • 高度仰賴自動化
  • 環境建置可以是 FVT or SVT 的條件。

Test Framework for Regression

單一的自動化測試難度不高,但是如果大量且要能夠團隊合作的 Test Framework 複雜度就很高,我設計過的 Test Framework 考慮以下:

  • 環境建置準備: 把環境弄到最乾淨,以 AWS 來說就是起一個乾淨的 Instance
  • 測試資料準備:每個 test case 都會有個別的測試資料,用來製造測試情境
  • 待測程式的部署或者安裝:從 build machine or S3 抓下最新的 build,安裝好後,把 test case 需要用的設定檔設定好
  • 單一 Test case 的開發流程與流程控制: tester 寫 test case 如何在自己的環境開發與測試
  • Test Suite 的管理與結構: 如何跑整個 test suites,test suites 本身的設定檔
  • Runner 的設計:
    • 跑單一 testcase,
    • 跟跑數個 suites 的設定檔, 然後可以個別指定設定檔, 或者 overwrite 每個 testcase 的設定檔
  • 測試排程控制 (分散式):
    • 如何同時跑多個 test case?
    • 排隊或者平行?
    • test case runtime 在哪一台機器跑?
    • 如果 test case 跑太久怎麼辦?這裡我設計了 duration 機制,也就是 tester 必須指定每個 test case 最長的執行時間,超過 test runner 就會把 thread 砍掉,並且執行 cleanup,把環境還原,把測試標記失敗。
  • 模擬程式的設計:有些測試程式需要製造一些特殊條件,像是 disk 滿了、CPU 80%、memory 沒了之類的 …
    • 我設計由 Framework 提供這些功能,tester 只要透過參數就可以達到想要的功能即可。
  • 額外的測試條件 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”:整個 Test Framework 自己的 Unit Test 以及 Libraries 都是透過自己測自己的方式實作,也就是自己的 Libraries 也會產生測試報表,每次加功能之前,都會用自己測自己 (當時我還不知道那叫 TDD)。這樣的想法是以前學 Java 時,聽學校老師說 Java Compiler 用什麼寫?當然是用 Java 寫囉!當時還不懂,後來就懂了。

下面是以前我設計 Test Framework for Regression 時規劃的流程與設計 (System Level Design),摘錄一些當時簡報的圖檔與心得:

程序的設計,有 Framework Level 和 User Level

測試程序的設計,有 Framework Level 和 User Level。Framework Level 根產品的特殊性有關係,產品相關的共用程序都封裝在 Framework 層,User Level 則是給 SQA 開發 Test Case 使用。

中間有一些 function,像是 Raise CPU, Memory Up,是由 Framework 控制。Tester 在開發 Test Case 時,只要指定參數就可以了。

Test Case 的目錄結構設計,參考 Java package 概念。

Test Cases / Test Suites 的目錄結構設計,參考 Java package 概念。而且 Suites 和 Test case 的設定檔具有繼承、annotation、branch 概念。branch 概念就是說屬於特定版本的設定,可以建立新的 設定檔,附加版本號碼,Framework 只要找到這樣的檔案,就會自動 overwrite 相關設定。

  • 類似 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 有簡單的描述。

這張圖是更大的測試流程圖,包含準備、自動更新 Firmware、Sequence / Parallel 的 Test Case 執行程序、以及 Log and Report。

這是執行後給 Testcase owner 的測試報告,列出 owner 每個 test case 的執行結果與 Log.

這張圖是測試資源的管理,Framework 會依據資源狀況,自動分配 Job。用 ZK 實作的。

我在 軟體自動化測試常見的問題 中問題到的描述,就是這段實作過程的經歷。

這一整套 Test Framework 是設計給一個團隊使用,裡面包含了協作、資源系統、報告、教育訓練、完整的文件手冊、範例程式碼、設計文件 … 等,當時一直想把他商品化,可惜並沒有機會。 (老了,要開始提當年勇了 XD)

Migration Test

有幾種混合的情境:

  • 通常是新舊程式 (database) 合併之後的測試。
  • 不同 app 版本對 server side 的差異測試

Migration 是很複雜的事情,所以 Plan 很重要,特別是需要長時間的執行,沒規劃好的 溝通成本 會非常驚人。

更多參閱:相容性與維護性

Performance Test

分成幾種: Stability, Reliability, Stress/Load Test, Capacity

作 Performance Test 的前提:FVT、SVT 要過。

我做 SQA Manager 的時候,本來是要去做 Performance Test,但是發現功能根本就不能用,所以就整個砍掉重來,先把 FVT 守住,直到通過率到一定程度之後,才開始 Performance Test。這段故事在 協同合作系統建制與導入 - 以 Redmine 為例 有提到一點。

環境建置考量:必須跟 Production 一致。

Stability (穩定性)

一定的資源之下:長時間,且大量的 Request 之下,系統維持在穩定狀況,不會有 CPU / Memory 凸波、或者是 Memory Leak、Disk I/O 瞬間的狀況。

如果應用程式本身具備 GC 機制,當記憶體使用量到一定程度時,則會自動恢復。

Reliability (可靠性)

  • 不論時間與條件的運作,如果系統發稱 Crash 狀況,恢復之後,所有的資料以及狀態都會恢復正常。
  • High Available, Fault Tolerance, Recoverability … 都是可靠性的實踐方法

更多參考 Goodle SRE: Site Reliability Engineering

Capacity (容量測試)

  • 一定的硬體資源,包含 Networking, Computing, Memory, Storage .. 等條件,應用程式能夠滿足多少的處理單位。
  • 放在 AWS 上的網站來說,使用 c4.large 的機器,最大能夠乘載多少的 HTTP Request,這個值稱為 Benchmark.
  • 有了 Benchmark 可以根據需求推論出系統需要的成本。例如已經知道 c4.xlarge 可以同時乘載 5k/second request,,那麼就可以推論如果有 100k/s request 需要準備多少台 c4.xlarge

Performance 測試除了上述面向,另一個面向就是帶測體是屬於整個 stack,還是 layer or tier

例如傳統的 web 有三層: Web -> Application -> DB,每個 layer 都有自己效能的問題,最終的目標是了解整個 stack 的 benchmark,但實際在執行上應該要先 bottom up,也就是先找到每一個 layer 自身的效能,最後才能測出 stack 的效能。

另一個例子是 realtime stream,像是影音串流的效能,先不考慮使用 p2p 技術,考慮使用 server relay 技術,一班實作就是: data source -> server relay -> client (app or web)

這三個端點都各自有傳輸的延遲時間 latency,每個節點都有運算時間,所以效能就包含兩個議題:

  • Latency: 資料傳輸時間,相依於網路,WAN -> Gateway / LAN / NAT / Wi-Fi … 等節點
  • Computing: 每個節點 encode / decode 的運算、protocol (RTSP)、mjpg / h264 … 等

從 Stack 的效能測試屬於 Top-Down View,大部分都會直接用這種方式開始,特別是沒有很多資源的狀況之下。一開始入門效能測試也都會從這個角度著手的比較多。

從 Layer 則屬於 Bottom-Up 方法,先找到每個 Layer 的 Capacity,然後再用數學方法模擬出整個系統的樣子,最後用 Infra as Code 的方式建立整套的系統,模擬測試。

效能測試的準備工作

如果是測試 Web System ,那就要花時間把整個系統建置起來,準備好測試資料,餵到 DB … 等。

實際上不只是待測要花時間準備,測試的 Client 的準備也是要花不少時間的,例如:

  • 測試程式的設計,模擬功能的行為。以 Live Stream 就是模擬 IPCam 的資料丟到 Server 然後傳給 App。
  • 測試程式執行環境的準備,要確認網路 Throughput 是否足夠
    • 測試環境能否自動化建置,最好利用像是 AWS CloudFormation 這樣的東西
    • 平常就要做好 Resource Provisioning 的工作。
    • 用 AWS 的話,確認機器等級的 Network 狀況,透過 VPC Flow Log 蒐集狀況
  • 測試流程 (HTTP Request) 模擬與建制,可以從既有的 Log 分析
  • 測試過程要蒐集的資料與 Log
  • 預期會產生的資料如何分析?

User Acceptance Test (UAT)

使用者接受度測試,一句話:出貨前最後驗證,要驗證什麼?

產品最重要的功能,最常走的路徑,那些功能就是 UAT

Field Test

前述的 Stage 都不是在 Production 測試,只有 Field Test 是正式環境,根 UAT 唯一的差異就是 環境,UAT 是在內部的環境, Field Test 則是在 Production。

其他領域

硬體生產領域也有類似的階段,主要的 DVT, EVT, PVT 三個階段。請參閱 Introduction to Embedded Systems 的介紹。

Strategies 策略

依據產品性質、專案執行的資源、時程、市場需求,會有不同的策略。策略由不同 Stage 組成,理想的條件,全部都要有,不過那是理想。

最基本的組合,也是很常見的組合,就是沒有測試就出貨了,嗯,沒有 QA 團隊的公司都是這個等級。

我認為,不能跟老闆妥協的,最基本的有兩個:FVT + RT。這是要守住的基本底線。

依照專案資源、時間狀況,過去我會搭配,有時候會搭 (FVT + SVT) + Migration + RT

FVT 我會直接跟 SVT 混著一起跑,Test case 直接設計成 E2E 就可以做到類似的,節省資源與時間。

CI: Continuous Integration

CI 有幾件事一定要有才算:

  • Build, Artifacts
  • Bind Build Information
  • Unit Test (Automatic)
  • Code Quality and Analysis

實際上要做到完整的不容易,有很多基礎建設要做。

相關概念參閱: Study Notes - CodeDeploy Preparation 第一段說明。

Resource Provisioning and Test

前述很多 Stages,不管哪一個都需要在正確的測試環境執行,換言之,錯誤的環境,會造成嚴重的資源浪費與狀況誤判。

Resource Provisioning 是測試的第一件重要事情,也是 DevOps 的第一件要事。實踐方法很多,可以使用 Container 技術,也可以用 Infra as Code 的方法。

建立測試環境還有一個很重要的目的,經常 review 現在整個系統的 Interface。系統之間的 Component 透過什麼方式串接?有多少 Endpoint?使用了哪一些第三方的 API Endpoint?Key?SSO?如果要建立一套新的系統需要先準備哪一些東西?那些東西好準備嗎?有 test 模式?像是信用卡測試帳號。

如果有經常做系統安裝以及 Review,基本上這些應該不是問題。Manager / PM 應該要清楚掌握這些東西,然後主動對外要資源。避免測試過程因為這些資訊不正確,造成測試結果不正確。

我在擔任 SQA Manager 基本上很少出現這問題,因為開測之前就會全部 ready。

詳細參閱:Resource Provisioning and DevOps

結論

測試應該是整個開發週期最長的時間,因為他需要把所有路徑都走過,把所有狀況都模擬過。

我的腦海裡常常有這樣的畫面:一個戰場上的戰士,還沒上戰場之前,有過嚴格的訓練,上戰場前就已經是傷痕累累,已經是經百戰。測試,就是上戰場前的準備。寧可多測,也不要隨意 Release。軟體的問題通常會是非線性的關係,覆水將難收,已經上戰場了,才來磨槍,只會死得更慘。

我從不相信『臨陣磨槍,不亮也光』這種屁話。

用吉他來說,測試就是一種練習,把每個音階、和弦、技巧練熟悉,一首歌練一百次算很少、一千次算可以上台表演。軟體也是,Release 之前能夠經過千錘百鍊,才會有品質。

延伸閱讀 (站內)

參考資料 (站外)


Comments