測試數據準備方法以及未來的發展方向

發表于:2019-05-16來源:TesterHome作者:劉春明點擊數: 標簽:
測試數據的準備,是軟件測試工作中非常重要的環節,無論是手工測試還是自動化測試都避不開測試數據準備工作。今天我們就來聊一聊測試工作中常用的測試數據準備的方法,深入了

測試數據的準備,是軟件測試工作中非常重要的環節,無論是手工測試還是自動化測試都避不開測試數據準備工作。今天我們就來聊一聊測試工作中常用的測試數據準備的方法,深入了解各自的優缺點和使用場景,以及測試數據準備工作未來的發展方向。

01 常見的測試數據準備方法

我總結了一下我曾經過用過的生成測試數據的方法,主要有以下幾類:

  • 基于 GUI 的測試數據生成方法

  • 基于 API 的測試數據生成方法

  • 基于 DB 的測試數據生成方法

  • 基于 MQ 的測試數據生成方法

  • 基于第三方庫方式的測試數據生成方法

  • 綜合運用上述方法生成測試數據

接下來,我們一起詳細分析一下各種方法的有權點以及適用場景。

基于 GUI 準備測試數據

基于 GUI 界面進行測試數據準備,是最原始的創建測試數據的方法,這種方法其實是采用 E2E 的方法來執行業務場景,然后得到測試數據。

比如,測試用戶登錄功能,那么需要準備的測試數據就是用戶賬號,為此我們可以通過 APP 或者 WEB 端的 GUI 頁面注冊新用戶,然后用這個用戶完成用戶登錄功能的測試。

這種方法的優點是簡單直接,創建的數據來自于真實的業務流程,最大程度保證了數據的正確性和完整性。在很多手工測試的場景中,這種方法被普遍采用。

但是,這種方法的缺點也非常明顯,主要體現在以下幾個方面:

  • 創建測試數據的效率低,不適合批量生成測試數據。因為通過 GUI 操作每次只能創造一條數據,而且通過手工操作 GUI 的過程也是比較耗時。

  • 基于 GUI 的測試數據生成方法不適合為自動化測試提供數據。由于自動化測試往往是通過代碼來準備測試數據,而 GUI 方法生成測試數據的方法不太適合封裝成代碼被自動化測試用例調用。因為封裝 GUI 方式生成測試數據的方法,本質上是在開發 GUI 自動化測試用例,而我們知道無論是開發工作量還是執行效率,亦或是穩定性方面,這種方法都是不是最佳的選擇。

  • 會引入不必要的測試依賴。比如測試用戶登錄功能,如果依賴 GUI 先注冊一個用戶,那么就意味著注冊功能必須是沒問題的,引入了依賴。這種情況,從數據庫中找到一個已注冊的賬號來測試登錄功能才是最佳選擇。

在前后臺配合的手工測試中,比如內容管理系統 CMS 和手機 APP 的測試,如果要手工測試手機 APP 的文章列表功能,那么就可以采用這種方法。除此之外,基于 GUI 操作生成測試數據的場景并不多。

基于 GUI 生成測試數據的方法,有一個非常重要的價值是幫助我們在創建測試數據的過程中,找到創建數據的過程中都調用了哪些 API 以及修改了哪些 DB 的表。只有了解了這兩個方面,我們后續通過 API 或者修改 DB 方式創建測試數據時,才能保證數據的完整性。

基于 API 準備測試數據

通過調用 API 生成測試數據,是目前測試數據生成的主要方法。由于后臺接口一般比較穩定,大大提供了測試數據構造的準確性和成功率。調用接口相比 GUI 操作也能夠比較快速的創建測試數據,效率高。另外,由于我們直接給 API 傳遞參數,通過參數的組合可以構造成某些 GUI 方法不能構造出來的測試數據。

那么,我們如何獲取到這些 API 呢?通常推薦按照下面的順序,來查找 API 相關的信息。

  1. API 接口文檔。通常成熟的開發團隊,都會編寫 API 的接口文檔,接口文檔中會詳細描述接口的 URI 和調用參數,這是最直接有效的辦法。

  2. 通過抓包。抓包在測試中是非常常用的輔助手段,我們可以在操作 APP 或者 WEB 頁面的時候,對操作進行抓包,通過對抓取到的請求包,分析接口的各種參數。這也是相對高效的辦法。

  3. 查看日志文件。對于已經上線的接口,我們可以通過服務的日志,來查看接口調用過程中的 URI 和參數等內容。

  4. 閱讀源碼。如果前面三種方法都不能用,那么可以在 Gitlab 上查看開發人員的項目代碼,通過閱讀代碼的方法,找到接口請求的各種參數。

通過 API 構造測試數據的方法也不是完美的,主要有幾個方面:

  1. 不是所有的數據創建都有對應的 API。

  2. 有時候需要順序調用多個 API。有時候測試數據之間是有關聯關系的,為了保證測試數據的完整性和一致性,需要依次調用多個 API,無形中增加了測試數據準備的復雜性。

調用 API 創建測試數據,天生適合與自動化測試相結合,在實際的測試實踐中,我們往往會把 API 封裝成測試數據準備函數供自動化測試用例使用。當 API 內部邏輯有修改時,我們依舊可以通過封裝函數來準備測試數據,對測試用例來說,是完全透明的。

這里所說的 API 指的是基于 HTTP 協議的 RESTful API。但是可以擴展到其他協議的各種調用接口,比如 MQTT 協議、RPC 協議等。

基于 DB 準備測試數據

通過往數據庫中直接插入數據,也是非常常用的構造測試數據的方法。具體做法是,將創建測試數據的 SQL 語句封裝成一個個測試數據生成函數,當我們創建數據時,直接調用這些封裝好的函數即可。這種方法有一個非常大的優點是生成測試數據的效率非常高,可以短時間內往數據庫中插入大量的測試數據。

以用戶登錄功能測試為例,當我們調用 API 進行用戶注冊時,這個 API 會將用戶的詳細的信息插入到 user 表和 role 表兩個數據庫表中。如果我們采用數據庫方式創造數據時,給 user 表和 role 表分別插入對應的數據就完成了用戶的注冊。我們還可以直接使用 DB 中已有的數據作為我們的測試數據,從而省去了很多操作。

這里的前提是,你必須知道進行新用戶注冊時,到底涉及到了哪些數據庫的表。最直接的辦法就是跟開發同學索要 SQL 語句,或者查看源代碼。

這種構造測試數據的方法也不是完美的,主要體現在以下幾個方面:

  1. 有的測試數據準備涉及到的數據表太多。導致封裝和維護測試準備函數的成本比較高。

  2. 容易出現數據不完整和不一致。比如服務 A 某一個業務,實際會在服務 A 的數據庫表 A 和數據庫表 B 中分別插入數據,并且同時會給 kafka 的某個 topic 發送數據供服務 B 消費處理后持久化到服務 B 的數據庫表 C 中。如果我們漏掉了某個數據庫表的插入操作,可能會導致數據的不完整和不一致。

基于 DB 準備測試數據的方法,通常作為 API 方法的補充。

基于 MQ 準備測試數據

在微服務架構中,通常會存在通過消息中間件將多個服務進行解耦,為了減少測試工作的依賴,通常會往 kafka 中構造測試數據。

比如,兩個服務是通過 KAFKA 進行消息傳遞的,兩個服務分別作為 kafka 的生成者和消費者。當我們測試作為消費者的服務時,就可以編寫 kafka 的 producer 代碼,往 kafka 中生產測試所需要的測試數據。具體的做法與通過 DB 構造測試數據的方式類似,將 kafka 的 producer 代碼封裝成測試數據生成函數,當我們創建數據時,直接調用這些封裝好的函數即可。

這種做法和操作 DB 并沒有本質不同,其優點和缺點也是類似的。

基于第三方庫準備測試數據

我們的測試實踐中,經常會需要生成很多隨機的數據,對于這類需求,直接使用代碼封裝成函數生成數據。拿 python 為例,可以自己結合 random() 之類的函數隨機生成數據,還可以使用 faker( 項目地址 )這樣的第三方庫來實現:

這類生成測試數據的方法試用的場景是,對數據本身的值不關心但是測試中又必須需要這些參數的情況。

綜合運用上述方法準備測試數據

在實際工作中,很少使用單一的方法就能滿足測試的需求,往往是綜合運用上述各種方法、一個典型的應用場景是,通過 API 生成最基礎的測試數據,比如車輛的 vid,然后使用數據庫和 MQ 的方法是生成符合測試需要的車輛狀態數據。

我以上報車輛狀態數據的測試為例子,來分享一下具體的如何將 API 調用和 MQTT 協議的方法結合起來構造測試數據。

比如我們要測試云端對車輛上報的報警數據的處理是否符合要求。首先,我們需要通過調用注冊 Vechile ID 的接口來注冊一臺車并且獲得車輛證書,通過調用這個接口我們可以得到一個車輛的 ID 以及證書數據。再結合 MQTT 協議產生車輛的報警數據。

為了構造測試數據的更加便捷,我們往往是對上面的操作進行封裝。用封裝后的方法產生測試數據。

02 準備測試數據的時機

前面介紹了準備測試數的方法,那么應該在什么時候創建好所需要的測試數據。是在測試用例執行中創建測試數據(On-the-Fly 方法)還是在測試執行前就準備好測試數據(Out-of-Box 方法)。

其實,創建測試數據的時機要根據實際的需要來。主要參考一下幾個因素:

  1. 創建測試數據所需要的時間。如果創建數據需要花很長時間,那么最好采用 Out-of-Box 方法,在測試執行之前就準備好,以減少整個測試執行的時間。

  2. 測試數據是否需要經常變動。如果測試數據不需要經常變動,那么最好采用 Out-of-Box 方法。如果事先生成數據在測試用例中會失效,比如具有有效期的數據,那么就適合采用 On-the-Fly 方法,在測試執行中創建。

  3. 測試數據是否存在于很多系統。如果測試數據需要在很多系統中都要創建各自的部分,各自又有很多依賴關系,那么就適合 Out-of-Box 方法。因為在測試用例執行中創建,會導致測試代碼比較臃腫,不夠清晰。

  4. 構造測試數據的服務是否穩定。在不太穩定的服務中構造測試數據,會產生大量構造測試數據失敗的情況。這種情況下采用 Out-of-Box 方法還是比較明智的。

接下來,我們詳細看一下 On-the-Fly 方法和 Out-of-Box 方法各自的特點,以及適用場景。

實時創建(On-the-Fly)

實時生成測試數據的方法,指的是在測試用例代碼執行過程中即時創建測試數據。比如,測試車輛駕駛中,不能執行遠程控制命令的場景。在測試執行中,可以通過封裝的 MQ 方法設置測試車輛的車輛狀態處于駕駛中,接下來就可以測試遠程執行命令了。

On-the-Fly 方法創造的測試數據通常是對每一個測試用例起作用的,不同的測試用例都有自己專屬的測試數據。像這種車輛狀態數據就適合采用 On-the-Fly 方法創造,這種狀態數據通常是每個測試用例都不同。這種構造測試數據的好處是,避免測試數據在測試用例執行前被修改而產生非預期的測試結果。這樣的測試數據使用完之后,通常在測試用例結束之后,恢復成原始數據,避免影響其他測試用例。

在自動化測試發展早期,測試實踐中通常都會這種方法,也是比較好的方法。他解決了測試用例之間數據之間干擾的問題,也避免了測試完之后的臟數據問題。但是隨著軟件架構的發展,以及測試頻率的提高,這種方式的弊端也逐漸顯示出來了,主要有以下幾個方面: 首先,有的測試數據比較耗時。 在測試用例執行過程中實時創建測試數據,會導致測試用例執行的時間被拉長。如果測試用例特別多,測試頻率又特別高,那么測試時間就變得特別長,這顯然不適合現在互聯網軟件的迭代節奏。為了解決測試耗時的問題,可以采用 Out-of-Box 方法。 其次,測試數據本身之間復雜的關聯性導致構造困難。 很多時候,你為了測試某一個場景,需要構造一堆相關聯的測試數據,也是偏向業務鏈后臺的測試數據,這個問題越明顯。

比如,要測試被授權人對車執行遠程控制命令的場景。會需要車主賬號、被授權人賬號、車輛 ID、車輛 ID 與車主賬號綁定,車主給被授權人授權車輛等前置數據。如果在測試用例執行中準備這些測試數據,那肯定是崩潰的。如果每一個測試用例都這么做,一定會導致測試時間變得非常長。為了解決這個問題,可以考慮將一部分穩定的數據事先創建好,比如車主賬號、被授權人賬號、車輛 ID 以及授權關系等數據。

微服務架構的流行導致成功生成測試數據的穩定性降低現在大量互聯網應用采用微服務架構,不同功能劃分為更多的微服務獨立開發和部署,很多時候測試環境里面,這些微服務并不是 100% 可用的。也就是說,不是任何時候構造測試數據都能成功。比如你測試的微服務 B,需要依賴微服務 A 構造數據,而這時候正好微服務 A 不可用,這就 block 了微服務 B 的測試。

為了解決上面的問題,事先準備測試數據的 Out-of-Box 方法,就有了用武之地。

提前準備(Out-of-Box)

Out-of-Box 方法,指的是在測試用例執行前,就已經準備好了所用的全部或者部分測試數據,而不是在測試用例中實施創建。因此,執行測試用例時候,可以節省不少準備測試數據的時間,同時也避免因為依賴的測試數據準備服務不可用導致測試被 block 的情況。

那么 Out-of-Box 方法是否也存在缺點呢?

最主要的問題是 “有效性” 問題,就是有測試執行中發現測試數據不可用的風險。比如,測試被授權人遠程執行車控命令的場景,當你執行測試時,發現被授人的身份已經被車主賬號刪掉了,這樣就導致測試用例執行失敗,也就不能順利完成測試了。

由此可見,這些實現創建好的測試數據,有可能在測試用例執行時已經不可用了,因為這些數據有可能已經進行了非預期的修改。比如,在其他測試用例執行時,使用了這個測試數據,并修改了這些數據的狀態。

為了解決這個問題,我們通常采用優化測試管理流程,讓不同的測試人員、測試業務都有自己獨立的測試數據,并且統計在 confluence、jira 或者其他公共平臺上,大家嚴格遵守,不要亂用測試數據。

另外,Out-of-Box 方法不適合準備,只能被使用一次的測試數據,只會使用一次的測試數據還是采用 On-the-Fly 方法準備比較合適。

實際工作中,我們通常是采用 On-the-fly 和 Out-of-box 這兩種方式相結合的方式來準備測試數據。我們可以根據測試目的的不同,將測試數據劃分為 “固定數據” 和 “易變數據”。比如某些測試場景中,車輛 ID、車輛 Profile、車主賬號等信息是相對穩定、不經常變化的數據,那么我們可以將這些測試數據稱為 “固定數據”,這類數據適合采用 Out-of-box 方式創建。但是在某些測試場景中,比如車輛 ID 的注銷,車輛 Profile 的變更測試,那么車輛 ID、車輛 Profile 就不能叫做 “固定數據” 而是應該叫做 “靈活數據”,這類數據適合采用 On-the-fly 方式準備。

綜合運用這兩類方法,可以滿足大部分測試數據準備的場景??梢越鉀Q準備測試數據耗時長、準備測試數據成功率不高等問題。

03 構造測試數據的痛點及應對

前面,我們分析了兩種準備測試數據的時機以及各自的優缺點。那么我們實際工作中,準備測試數據的工作有哪些痛點,我們又該如何解決呢?

調用封裝函數的復雜性

前面提到封裝 API 到一個函數,然后調用這個函數來構造測試數據的方法。但是這種封裝方式會有問題,就是如果參數非常多,那么你調用它來構造數據時,就要準備這些參數。如果這些參數是基本類型的話還好,如果參數本身也是對象的話,可能就會更加麻煩了,因為你要創建這些對象。而創建這些對象,有可能要繼續調用其他封裝的函數,從而牽連出一系列函數調用的操作。

比如,調用這樣一個封裝了注冊車輛 vid 的函數:

由此可見,每次使用封裝的函數準備測試數據時,我們要給函數傳遞所有的參數。其實大多數測試場景下,所有參數都可以給一個默認值,用這個函數準備測試數據時,只需要給那些有明確要求的參數傳值,其他參數保持默認值即可。這樣封裝的函數就變成這樣:

這樣,大大減少了調用封裝函數的成本。當測試用例中只需要一個特定 vin 的車輛時,只需要給 register_vehicle 傳遞參數 vin 的值,其他的測試用例不關心的參數都可以保持默認值。

封裝函數的版本管理

通常我們封裝函數是給所有的測試項目共同使用的,這樣才能最大化封裝函數的價值。共享封裝函數的辦法通常是將其打包,然后在其他項目中引用。如果你的測試項目是使用 Python,那么可以將封裝的函數用 setuptools 打包上傳到公司的 Pypi 平臺,在測試的項目中用 pip 安裝。如果你的測試是使用 Java,可用 Maven 將封裝函數打成 Jar 包并上傳到公司的私有倉庫,在測試項目中的 pom.xml 中引入 jar 包就好了。

現在的互聯網應用版本迭代更新特別快,導致封裝函數也要對應的迭代更新。這就會產生數據準備函數的包升級更新比較頻繁,包的版本號就要隨著變化。所以引用了這些數據準備函數包的項目,就要更新包的版本。給使用者帶來了一些麻煩。

為了解決項目對封裝函數的依賴問題,我們可以將其做成 Restful API,這樣使用者就免去了頻繁更新這些依賴包的麻煩。而且 Restful API 天生的跨平臺支持,讓調用方不管是用 Java 寫測試用例還是 Python 寫測試用例,都可以得到完美的支持。接下來我們就詳細介紹一下基于 Restful API 的測試數據準備方案。

04 統一測試數據生成平臺

前面介紹了創建測試數據的主要方法、創建測試數據的時機,以及測試數據生成中的痛點。隨著測試技術的發展,測試數據準備技術與架構也需要逐步進化,來滿足互聯網微服務架構的發展趨勢以及快速迭代的特點。

現在業界,將測試數據準備的工作進行平臺化,逐漸成為測試數據準備方案的發展方向。而 Restful API 的測試數據準備方案,正好適合平臺化的發展方向。我們可以將基于 Java 開發的數據準備函數用 Spring Boot 包裝成 Restful API,或者將基于 Python 開發的數據準備函數用 Flask 或者 Django REST framework 包裝成 Restful API。

這樣一來,測試人員可以通過 Restful API 調用來準備測試數據了,由于 HTTP 協議是跨平臺的,所以幾乎所有的測試框架都可以直接使用這些 Restful API 準備測試數據。由于使用 Restful API 提供測試數據,這樣方便我們將提供各類測試數據的服務整合到一起,形成 “統一測試數據生成平臺”。結合 Swagger 提供的界面化文檔,可以方便看到接口調用的方法,并且可以直接在界面上調用接口生成數據。既滿足自動化測試的需要,也能滿足手工測試的需求。

目前為止,我們將測試數據準備工作進行了服務化,下圖就是一個統一測試數據生成平臺的 Restful API 界面。

統一測試數據平臺 Restful API UI 界面

" 統一測試數據平臺 " 從提供的測試數據特性來分,可以分為真實數據和 Mock 數據。真實數據就是封裝微服務的接口,在業務系統中實際產生真實的業務數據用作測試數據。Mock 數據是指通過 mock 技術產生非實際業務中的數據、這類數據一般用于解決服務依賴問題。

提供真實數據

下面通過 Flask Web 框架來介紹如何通過封裝業務操作提供真實的測試數據實踐。

比如,我要測試遠程控制車輛的 API,其中有一個測試用例是驗證在車輛在行駛中時不能進行遠程控制。針對這個測試用例,我們需要的測試數據有被控制車輛的 ID 以及車輛狀態。下面以準備車輛 ID 的 Restful API 為例,介紹具體的實現方式。

首先,使用 pipenv 創建虛擬環境,安裝好 Flask 框架。

下面這段代碼是封裝了業務接口 api/1/in/vehicle/profile 的代碼片段。

在這段代碼中,提供默認參數,只需要傳遞測試感興趣的參數就可以,不感興趣的數據保持默認值即可。結合 flasgger 提供的 swag_from 裝飾器,給接口編寫文檔,讓封裝的接口易懂和易用。

提供 Mock 數據

什么情況下需要 Mock 數據,比如:服務 A 調用服務 B 的 Restful API,傳遞給服務 B 數據,服務 B 會根據數據情況返回給服務 A 一個 ACK 值。當服務 B 沒有 Ready 時候,我們就需要模擬服務 B 的行為。

其實產生這種 Mock 數據,與前面介紹的產生實際業務數據,方法上并沒有不同。只是在 Restful API 的 response 構造上,前者構造產生的數據來自與真實的業務接口,而 Mock 的數據是根據測試需求偽造的。模擬前面提到的服務 B 的行為,以 Flask 方案為例,就是:

通過控制上面 ack 的內容,就可以模擬服務 B 的各種 Response 了。如果將這個 ack 的內容存入數據庫中,讓 get_ack 函數從數據庫中取得 ack 并返回。再寫一個接口用于往數據庫中寫入 ack,那么就可以在自動化測試中隨意控制 ack 的返回內容了。

05 總結

本篇文章我們梳理了測試數據準備的各種方法,并分析了各自的優缺點及適用場景。測試數據準備的時機上看,對于不常改變的數據適合采用提前準備的方法,對于經常變化的數據在測試用例中準備更好。對測試工作中數據準備的痛點進行了剖析并給出了應對方案。最后,給出了解決測試數據生成痛點的終極解決方案——" 統一測試數據生成平臺 "。


原文轉自:TesterHome

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97