模型測試系統是zstack-woodpecker中的一個子項目。經過有限狀態機和行爲選擇策略,它能夠產生隨機的API操做,一直運行下去,直到遇到一個缺陷或者預約義的退出條件。ZStack依賴模型測試去測試真實世界中難以遇到的邊界用例,在測試覆蓋度方面補充集成測試和系統測試。算法
測試覆蓋率是一個判斷一個測試系統品質的重要指示器。常規測試方法論,例如單元測試,集成測試,系統測試,都是由人類邏輯思考構建的,難以覆蓋軟件中的邊界場景。這個問題在IaaS軟件中變得更加明顯,由於管理不一樣的子系統會致使極爲複雜的場景。工具
ZStack經過引入基於模型的測試來解決這個問題。它能夠產生由隨機API組合構成的場景,會持續運行知道遇到預約義的退出條件或者找到一個缺陷。做爲機器驅動的測試,基於模型的測試能夠克服人類邏輯思考的缺陷來執行一些,看起來反人類邏輯,可是API徹底正確的測試,幫助發現難以被人類主導的測試發現的邊界問題。單元測試
一個例子能夠幫助理解這個思想。基於模型的測試系統一般在執行大約200個API後暴露一個bug,在調試後,咱們找到最小重現這個問題的序列是:測試
這個操做序列顯然是反邏輯的,咱們相信沒有測試者會寫一個集成測試用例或者系統測試用例這麼作。這就是機器思考閃光的地方,由於它沒有人類的感情,會作人類感受不合理的事情。在找到這個bug以後,咱們生成了一個迴歸測試爲之後保障這個問題。spa
基於模型的測試系統,由於由機器驅動,也被稱爲機器人測試。當這個系統運行時,它從一個模型(在下面幾節中也被稱爲階段)移動到另外一個模型,經過執行被動做選擇策略選出的動做(也被稱爲操做)。在每個模型完成以後,檢查器將會驗證測試結果,測試退出條件。若是任何失敗被發現,或者退出條件被知足,系統將會退出。不然,它將會移動到下一個模型,而後重複。插件
在基於模型的測試的理論中,有許許多多生成測試操做的方式。例如:有限狀態機,自動推導,模型檢驗。咱們選擇使用有限狀態機,由於它天然地適合IaaS軟件,其中每個資源都由狀態驅動。例如,從用戶角度看,VM的狀態像這樣:調試
在基於模型的測試系統中,每個資源的每個狀態都預先定義在test_state.py中,看起來像:日誌
系統中全部資源的全部狀態構成一個階段(模型),系統能夠從一個階段轉移到下一個階段,經過執行維護在轉換表中操做。一個階段被定義成相似這樣:blog
一個階段能夠被表示成一個整數,即由這個階段的全部狀態的和。經過這個整數,咱們能夠在轉換表中查找到下一個後選的操做。轉換表的一個例子以下:資源
經過這種方式,基於模型的測試系統能夠保持運行,從一個階段到另外一個階段,直到遇到預先定義的退出條件或者發現一些缺陷,它能夠持續地跑不少天,數以萬次地調用API。
當在階段間移動時,基於模型的測試系統須要決定下一個須要執行的操做是什麼。決定製定器被稱爲動做選擇策略,一個可擴展插件的引擎,不一樣的選擇算法能夠以不一樣的目的被實現。
當前系統有三種策略:
1.隨機調度器:最簡單的策略,爲當前的階段,從候選動做中隨機地選擇下一個操做。做爲一種很直接的算法,隨機調度器可能會重複一項操做,而使得其餘操做等待。爲了緩解這個問題,咱們爲每個操做都增長了一個權重,這樣測試人員能夠爲他們想多測試的操做賦予更高的權重。
2.公平調度器:一種對待每一個操做都徹底平等的策略,以這樣一種方式補充隨機調度器:每一個操做都有平等的機會被執行,保證只要測試周期足夠長,每一個操做都會被測試到。
3.路徑覆蓋調度器:經過歷史數據決定下一步操做的策略。這個策略會記住已經被執行過的全部操做路徑,而後嘗試選擇一個能夠造成新的操做路徑的操做。例如,給定候選操做A,B,C,D,若是前一個操做時B且路徑BA,BB,BC都已經被執行,策略將會選取D做爲下一個操做,這樣路徑BD將會被測試到。
如上面說起到的,動做選擇策略是一個可擴展插件的引擎,每個策略實際上由類ActionSelector派生來:
一個隨機調度器的實現例子像這樣:
在啓動基於模型的測試系統以前,退出條件必須被設定好,不然系統將會保持運行,直到一個缺陷被發現,或者日誌文件撐爆了測試機器的硬盤。退出條件能夠是任何形式的,例如,在運行24小時後退出,在系統有100個EIP被建立後退出,在有2箇中止的VM、8個運行中的VM時退出。一切都取決於測試者去定義條件,儘量地增長髮現缺陷的機會。
調試一個被基於模型的測試系統發現的失敗是很難並且使人沮喪的,大多數的失敗都由大量的操做序列暴露,並且它們一般缺少邏輯並有着大量的日誌。咱們一般手動重現失敗,在痛苦地依照大約500,000行日誌,使用zstack-cli調用API 200次後,咱們最終意識到這個悲慘的任務不是人類能夠作到的。而後咱們發明了一個工具用於重現一個失敗,經過回放動做日誌(純粹只記錄了關於API的測試信息)。
一個動做日誌像這樣:
測試人員能夠經過調用回放工具重建失敗的環境:
在這篇文章中,咱們引入了基於模型的測試系統。因爲善於暴露邊界用例中的問題,基於模型的測試系統和集成測試系統、系統測試系統共同做爲保衛ZStack質量的基礎,使得咱們能夠以驕傲的自信發佈產品。