1. 程式人生 > 實用技巧 >軟體測試回顧(9)-準備測試資料

軟體測試回顧(9)-準備測試資料

軟體測試回顧(9)

準備測試資料


35章:如何準備測試資料?

測試資料準備方法主要可以分為四類:

  • 基於GUI操作生成測試資料;
  • 通過API呼叫生成測試資料;
  • 通過資料庫操作生成測試資料;
  • 綜合運用API和資料庫的方式生成測試資料。

1.基於GUI操作生成測試資料

優點:

  • 在技術上沒有任何複雜性,而且所建立的資料完全來自於真實的業務流程,
  • 可以最大程度保證資料的正確性。

缺點:

  • 建立測試資料的效率非常低
  • 基於GUI的測試資料建立方法不適合封裝成測試資料工具
  • 測試資料成功建立的概率不會太高
  • 會引入不必要的測試依賴。如:要測試登入功能,首先就要保證註冊功能沒問題的。

在實際的測試過程中,我們很少直接使用基於GUI的操作生成測試資料。基於GUI操作生成測試資料的方法一般只用於手工測試

2.基於API呼叫生成測試資料

通過API呼叫生成測試資料,是目前主流的測試資料生成方法。

為了規避在建立測試資料時過於在乎實現細節的問題,在實際工程實踐中,我們往往會把呼叫API生成測試資料的過程封裝成測試資料準備函式

怎麼才能知道到底呼叫了哪些後端API呢?這裡,我推薦三種方式:

  • 直接詢問開發人員,這是最直接的方法;
  • 如果你有一定的程式碼基礎,可以直接閱讀原始碼,這個方法也可以作為直接詢問方法的補充;
  • 在一個你可以獨佔的環境上執行GUI操作建立測試資料,與此同時監控伺服器端的呼叫日誌,分析這個過程到底呼叫了哪些API。

優點:

  • 保證建立的測試資料的準確性
  • 執行效率更高
  • 建立測試資料的API呼叫過程,封裝成測試資料函式更方便,因為這個呼叫過程的程式碼邏輯非常清晰;
  • 依賴於API呼叫,當建立測試資料的內部邏輯有變更時,由於此時API內部的實現邏輯也會由開發人員同步更新

缺點:

  • 並不是所有的測試資料建立都有對應的API支援。
  • 建立一條業務線上的測試資料,往往需要按一定的順序依次呼叫多個API,並且會在多個API呼叫之間傳遞資料,這也無形中增加了測試資料準備函式的複雜性。
  • 執行速度上已經得到了大幅提升,並且還可以很方便地實現併發執行,但是對於需要批量建立海量資料的場景,還是會力不從心。

3.通過資料庫操作生成測試資料

通過資料庫操作生成測試資料,也是目前主流的測試資料生成方法。

常見的做法是,將建立資料需要用到的SQL語句封裝成一個個的測試資料準備函式,當我們需要建立資料時,直接呼叫這些封裝好的函式即可。

這樣做的前提是,你需要知道前端使用者通過GUI操作註冊新使用者時,到底修改了哪些資料庫的業務表。這裡,我也推薦三種方式:

  1. 直接向開發人員索要使用到的SQL語句;
  2. 直接閱讀產品原始碼;
  3. 在一個你可以獨佔的環境上執行GUI操作產生測試資料,與此同時,監控獨佔環境的資料庫端業務表的變化,找到哪些業務表發生了變化。

缺點:

  • 一個前端操作引發的資料建立,往往會修改很多張表,因此封裝的資料準備函式的維護成本要高得多
  • 容易出現數據不完整的情況,這種錯誤一般都會比較隱蔽,往往只在一些特定的操作下才會發生異常;
  • 當業務邏輯發生變化時,即SQL語句有變化時,需要維護和更新已經封裝的資料準備函式

4.綜合運用API和資料庫的方式生成測試資料

最典型的應用場景是,先通過API呼叫生成基礎的測試資料,然後使用資料庫的CRUD操作生成符合特殊測試需求的資料


36章:測試資料建立的時機

要分為On-the-fly(實時建立)和Out-of-box(事先建立測試資料)兩類方法。

1.On-the-fly(實時建立)

在測試用例的程式碼中實時建立要使用到的測試資料。

採用On-the-fly方式建立的資料,都是由測試用例自己維護的,不會依賴於測試用例外的任何資料,從而保證了資料的準確性和可控性,最大程度地避免了出現“髒”資料的可能

缺點:

  • 實時建立測試資料比較耗時
  • 測試資料本身存在複雜的關聯性
  • 微服務架構的調整
    • 很多時候測試環境並不是100%處於全部可用的狀態。也就是說,並不是所有的服務都是可用的,這就給測試資料準備帶來了新的挑戰。

2.Out-of-box(事先建立)

為了解決上述三個問題,Out-of-box(即事先建立測試資料)的方式就應運而生

Out-of-box方法,又稱開箱即用方法,指的是在準備測試環境時就預先將測試需要用到的資料全部準備好,而不是在測試用例中實時建立。

缺點:

Out-of-box最致命的問題是“髒”資料。

那到底什麼是“髒”資料呢?這裡的“髒”資料是指,資料在被實際使用前,已經被進行了非預期的修改。

這些事先建立好的測試資料,在測試用例執行的那個時刻,是否依然可用其實是不一定的,因為這些資料很有可能在被使用前已經發生了非預期的修改。

這些非預期的修改主要來自於以下三個方面:

  1. 其他測試用例使用了這些事先建立好的測試資料,並修改了這些資料的狀態;
  2. 執行手工測試時,因為直接使用了事先建立好的資料,很有可能就會修改了某些測試資料;
  3. 自動化測試用例的除錯過程,修改了事先建立的測試資料;

為了解決這些“髒”資料,我們只能通過優化流程去控制資料的使用。業內有些公司會將所有事先建立好的測試資料列在一個Wiki頁面,然後按照不同的測試資料區段來分配使用物件。

更糟糕的是,如果自動化測試用例直接採用硬編碼的方式,去呼叫那些只能被一次性使用的測試資料(比如訂單資料、優惠券等)的話,你會發現測試用例只能在第一次執行時通過,後面再執行都會因為測試資料的問題而失敗。

Out-of-box方法不適用於只能一次性使用的測試資料場景。

3.綜合運用On-the-fly和Out-of-box

實際的工程實踐中,往往是採用綜合運用On-the-fly和Out-of-box的方式來實現測試資料的準備的。

在實際的測試專案中,我們可以根據測試資料的特性,把它們分為兩大類,用業內的行話來講就是“死水資料”和“活水資料”。

“死水資料”是指那些相對穩定,不會在使用過程中改變狀態,並且可以被多次使用的資料。比如,商品分類、商品品牌、場館資訊等。這類資料就非常適合採用Out-of-box方式來建立。

這裡需要特別說明的是,哪些資料屬於“死水資料”並不是絕對的,由測試目的決定。

比如,使用者資料在大多數的非使用者相關的測試用例中基本屬於“死水資料”,

但是,對於那些專門測試使用者賬號的測試用例來講,往往會涉及到使用者撤銷、啟用、修改密碼等操作,那麼此時的使用者資料就不再是“死水資料”了,而應該按照“活水資料”處理。

“活水資料”是指那些只能被一次性使用,或者經常會被修改的測試資料。最典型的資料是優惠券、商品本身、訂單等類似的資料。這類資料通常在被一次性使用後狀態就發生了變化,不能反覆使用。那麼這類測試資料,就更適合採用On-the-fly方式來建立。

個人覺得一定要大家使用一套產生測試資料的指令碼,無論是api還是資料庫,做到一鍵配置、恢復測試資料。還有就是死水資料的準備大家最好有統一的平臺進行發放,而不是隨便寫,隨便測


37+38章:統一測試資料平臺

1.測試資料準備1.0時代

這個階段最典型的方法就是,將測試資料準備的相關操作封裝成資料準備函式

利用這種資料準備函式建立測試資料方法的最大短板,在於其引數非常多、也非常複雜

其實,絕大多數的測試資料準備場景是,你僅僅需要一個所有引數都使用了預設值的測試資料,或者只對個別幾個引數有明確的要求,而其他引數都可以是預設值的測試資料

為了解決這個問題,在工程實踐中,就引入瞭如圖1所示的封裝資料準備函式的形式。

當測試用例中僅僅需要一個沒有特定要求的預設使用者時,你就可以直接呼叫這個createDefaultUser函式,

對於那些測試用例只對個別引數有要求的場景,比如只對引數A有要求的場景,我們就可以為此封裝一個createXXXUser(A)函式,用預設值初始化引數B、C、D、E,然後對外暴露引數A。

如果是對多個引數有特定要求的場景,我們就可以封裝出createYYYUser這樣暴露多個引數的函式。

通過這樣的封裝,對於一些常用的測試資料組合,我們通過一次函式呼叫就可以生成需要的測試資料;而對於那些比較偏門或者不常用的測試資料,我們依然可以通過直接呼叫最底層的createUserImpl函式完成資料建立工作。可見,這個方法相比之前已經有了很大的進步。

缺點:

  • 對於引數比較多的情況,會面臨需要封裝的函式數量很多的尷尬
  • 當底層Impl函式的引數發生變化時,需要修改所有的封裝函式。
  • 資料準備函式的JAR包版本升級比較頻繁
    • 一旦封裝的資料準備函式發生了變化,我們就要升級對應JAR包的版本號。

為了可以進一步解決這三個問題,最大程度地簡化測試資料準備工作,將測試資料準備推向了2.0時代。

2.測試資料準備2.0時代

資料準備函式不再以暴露引數的方式進行封裝了,而是引入了一種叫作Builder Pattern(生成器模式)的封裝方式。這個方式能夠在保證最大限度的資料靈活性的同時,提供使用上的最大便利性,並且維護成本還非常低。

就是之前是程式碼直接呼叫生成函式,而現在是生成函式類似使用了生成器設計模式而已

你需要準備一個使用者資料,而且對具體的引數沒有任何要求。

UserBuilder.build();

你現在還需要一個使用者,但是這次需要的是一個美國的使用者。

UserBuilder.withCountry("US").build();

你又需要這樣一個使用者資料:英國使用者,支付方式是Paypal,其他引數都是預設值。

UserBuilder.withCountry("US").withPaymentMethod("Paypal").build();

在實際工程專案中,隨著Builder Pattern的大量使用,又逐漸出現了更多的新需求,為此我歸納總結了以下4點:

  • 有時候,出於執行效率的考慮,我們不希望每次都重新建立測試資料,而是希望可以從被測系統的已有資料中搜索符合條件的資料;
  • 但是,還有些時候,我們希望測試資料必須是全新建立的,比如需要驗證新建使用者首次登入時,系統提示修改密碼的測試場景,就需要這個使用者一定是被新建立的;
  • 更多的時候,我們並不關心這些測試資料是新建立的,還是通過搜尋得到的,我們只希望以儘可能短的時間得到需要的測試資料;
  • 甚至,還有些場景,我們希望得到的測試資料一定是來自於Out-of-box的資料。

為了能夠滿足上述的測試資料需求,我們就需要在Builder Pattern的基礎上,進一步引入Build Strategy的概念。顧名思義,Build Strategy指的是資料構建的策略。

就是在簡單的生成器模式下合入了策略模式,,通過策略進行生成

我們引入了Search Only、Create Only、Smart和Out-of-box這四種資料構建的策略。這四類構建策略在Builder Pattern中的使用很簡單,只要按照以下的程式碼示例指定構建策略就可以了:

UserBuilder.withCountry(“US”).withBuildStrategy(BuildStrategy.SEARCH_ONLY.build();
UserBuilder.withCountry(“US”).withBuildStrategy(BuildStrategy.CREATE_ONLY).build();
UserBuilder.withCountry(“US”).withBuildStrategy(BuildStrategy.SMART).build();
UserBuilder.withCountry(“US”).withBuildStrategy(BuildStrategy.OUT_OF_BOX).build();

這裡的Builder Pattern是基於Java程式碼實現的,如果你的測試用例不是基於Java程式碼實現的,那要怎麼使用這些Builder Pattern呢?我們不希望、也不可能為每套基於不同開發語言的測試框架都封裝一套Builder Pattern。所以,我們就希望一套Builder Pattern可以適用於所有的測試框架,這也就是我在前面提到的測試準備函式的“跨平臺的能力”了

為了解決這個問題,測試資料準備走向了3.0時代。

3.測試資料準備的3.0時代

為了解決2.0時代跨平臺使用資料準備函式的問題,我們將基於Java開發的資料準備函式用Spring Boot包裝成了Restful API,並且結合Swagger給這些Restful API提供了GUI介面和文件。

就是將測試準備函式 變成了web工具,通過restful api進行統一呼叫,來實現跨平臺

我們就可以通過Restful API呼叫資料準備函數了,而且由於Restful API是通用介面,所以只要測試框架能夠發起http呼叫,就能使用這些Restful API。於是,幾乎所有的測試框架都可以直接使用這些Restful API準備測試資料。

最初,統一測試資料平臺就是服務化了資料準備函式的功能,並且提供了GUI介面以方便使用者使用,除此以外,並沒有提供其他額外功能。如圖1所示就是統一測試資料平臺的UI介面。

後來,隨著統一測試資料平臺的廣泛使用,我們逐漸加入了更多的創新設計,統一測試資料平臺的架構也逐漸演變成了如圖2所示的樣子。

接下來,我和你分享一下統一測試資料平臺的架構設計中最重要的兩個部分:

  1. 引入了Core Service和一個內部資料庫。其中,內部資料庫用於存放建立的測試資料的元資料;Core Service在內部資料庫的支援下,提供資料質量和數量的管理機制。
  2. 當一個測試資料被建立成功後,為了使得下次再要建立同類型的測試資料時可以更高效,Core Service會自動在後臺建立一個Jenkins Job。這個Jenkins Job會再自動建立100條同類型的資料,並將建立成功的資料的ID儲存到內部資料庫,當下次再請求建立同類型資料時,這個統一測試資料平臺就可以直接從內部資料庫返回已經事先建立的資料。
    在一定程度上,這就相當於將原本的On-the-fly轉變成了Out-of-box,縮短整個測試用例的執行時間。當這個內部資料庫中存放的100條資料被逐漸被使用,導致總量低於20條時,對應的Jenkins Job會自動把該型別的資料補足到100條。而這些操作對外都是透明的,完全不需要我們進行額外的操作。

我看老師的留言下面有個人說怎麼一直在科普概念。我認為老師的這段回覆很好

很多時候概念本身比會使用工具來得重要的多,對於測試資料準備的文章中介紹的很多方法和理念都是外面找不到的,都是來自於大專案中的工程實踐,如果大家對工具本身的使用更感興趣,我還是建議通過官方文件進行學習,但是怎麼找到適合你的工具,以及學習這些工具設計的思路,還是要能夠掌握原理。