teprunner測試平台測試計劃批量運行用例
本文開發內容
上一篇文章已經把pytest引入到測試平台中,通過多執行緒和多進程的方式,運行測試用例。有了這個基礎,做批量運行用例的功能就很簡單了,只需要前端傳入一個CaseList即可。本文的後端程式碼是增刪改查和復用run_case相關程式碼做個run_plan。前端程式碼將學習如何通過LocalStorage在非父子組件之間傳遞數據。具體開發內容如下:
- 測試計劃增刪改查
- 測試計划動態添加移除測試用例
- 運行測試計劃,批量運行用例
- 計劃運行結果、用例運行結果
編寫後端程式碼
編輯teprunner/urls.py文件,添加測試計劃的路由:
編輯teprunner/models.py文件,添加3張表的model:
Plan存放測試計劃,PlanCase存放計劃和用例關聯關係,PlanResult和CaseResult類似,這裡之所以把單獨出來一張結果表,是為了和用例結果CaseResult相互獨立,防止計劃結果覆蓋用例結果,畢竟CaseResult一般是手工跑出來的,PlanResult一般是定時任務跑出來的,功能數據解耦後處理起來也更方便。
編輯teprunner/serializers.py文件,添加序列化器:
為了前端展示需要,這裡額外關聯了一些欄位進行展示。尤其是:
caseNum用例總條數,passedNum成功條數,failedNum失敗條數,errorNum錯誤條數。成功定義為:只有passed,沒有failed和error的用例。失敗定義為:只有failed,沒有error的用例。錯誤定義為:只要有error的用例。
本文還展示了,如果序列化器的某個欄位只在存庫時使用,返迴響應時不展示,該怎麼處理:
重寫to_representation方法,把不需要返回的欄位pop移出去。這裡output在計劃運行結果不需要,在用例運行結果才需要,為了減少傳輸數據,就在計劃運行結果的介面響應中移出去了。
最後來寫View,新增teprunner/views/plan.py文件:
重寫list方法,添加查詢條件。重寫destroy方法,判斷必須先刪除關聯測試用例,才能刪除測試計劃。
PlanCaseView類似:
添加add方法:
在添加用例時寫入plan_case表。添加remove方法:
在移除用例時從plan_case表刪除數據。繼續:
result視圖用來返回計劃運行結果,根據searchType來分別查詢用例總條數、成功條數、失敗條數、錯誤條數。
繼續:
plan.case_result和case.case_result類似,返回測試計劃的每條用例的運行結果。
在測試計劃添加用例的時候,有個用例列表,需要增加2個過濾條件,編輯teprunner/views/case.py文件:
第一個過濾條件是排除當前計劃已經添加過的用例:exclude_plan_id由前端傳入,根據PlanCase關聯關係找到已添加的用例進行過濾;第二個查詢條件是關鍵字:用例ID或用例描述,跟PlanCaseView.list()裡面一樣。
最後,編輯teprunner/views/run.py文件,增加批量運行用例的功能:
添加delete_plan_result方法,在運行用例前,先把已有結果刪掉,注意這裡的model是PlanResult。繼續:
修改pytest_subprocess函數,添加plan_id欄位。繼續:
修改save_case_result函數,判斷沒有plan_id就存case_result表,有plan_id就存plan_result表。
複製run_case的程式碼為run_plan:
修改case相關程式碼為plan。值得注意的是中間那段程式碼,根據plan_id從PlanCase中找到關聯用例,生成了case_list,這樣就復用run_case的多執行緒和多進程程式碼,批量運行測試用例了。
編寫前端程式碼
編輯src/router/index.js文件,添加測試計劃相關路由:
{
path: "plan",
name: "plan",
meta: {
title: "測試計劃",
},
component: () => import("@/views/teprunner/plan/PlanManagement.vue"),
children: [
{
path: "addPlan",
name: "addPlan",
meta: {
title: "添加計劃",
},
component: () => import("@/views/teprunner/plan/PlanEditor"),
},
{
path: "editPlan",
name: "editPlan",
meta: {
title: "編輯計劃",
},
component: () => import("@/views/teprunner/plan/PlanEditor"),
},
{
path: "caseList",
name: "caseList",
meta: {
title: "用例列表",
},
component: () => import("@/views/teprunner/plan/CaseList"),
},
{
path: "planResult",
name: "planResult",
meta: {
title: "計劃運行結果",
},
component: () => import("@/views/teprunner/plan/PlanResult"),
children: [
{
path: "caseResult",
name: "caseResult",
meta: {
title: "用例運行結果",
},
component: () => import("@/views/teprunner/plan/CaseResult"),
},
],
},
],
},
跟之前做增刪改查不一樣的地方是:在父組件中,不會import子組件,而是通過LocalStorage進行組件之間傳值。因此這裡增加了添加計劃、編輯計劃等路由。
編輯src/views/teprunner/index.vue文件:
添加測試計劃左側菜單。
新建src/views/teprunner/plan目錄,新建src/views/teprunner/plan/PlanManagement.vue文件:
項目環境根據路由不同,分別展示,路由plan是測試計劃主頁面,同時展示項目和環境。路由addPlan新增計劃不需要展示環境。路由editPlan編輯計劃,不需要展示環境,且項目不能修改。接著添加了<div>
主路由介面,通過v-if
來判斷是否為主路由。<router-view>
是用來展示路由的頁面容器,addPlan和editPlan的組件經過主路由的this.$router.push()
後,會載入到這個容器里。
就像用例結果一樣,我給不同計劃結果區分了顏色和鏈接:
繼續:
運行計劃和刪除計劃跟之前寫的程式碼相差不大。
繼續:
這就是LocalStorage給組件傳數據的關鍵程式碼。先存數據,再跳轉路由,這個路由會載入到前面添加的<router-view>
容器中。
新建src/views/teprunner/plan/PlanEditor.vue文件:
這是新增和修改計劃的組件,在created()時讀取localStorage中主頁面存入的數據。在這個頁面繼續添加程式碼:
點擊取消按鈕後,返回上一級路由:測試計劃主頁面。
新增或修改後,返回測試計劃主頁面,需要立即展示新數據:
通過watch來監測,每次路由跳轉到plan時,就查詢一次表格數據。
新建src/views/teprunner/plan/CaseList.vue文件:
在created()讀取數據。這個地方有個彈出框,用到了selection-panel:
這在用戶管理,新增用戶選擇角色時已經介紹過了。此時需要加點東西,添加一個查詢條件用來過濾測試用例,編輯src/components/SelectionPanel.vue文件:
添加了總項數,和查詢輸入框。繼續:
這幾個組件的函數很多都添加了async關鍵字,表示非同步。這麼做是為了頁面操作看起來更流暢,防止添加移除頻繁操作導致頁面卡住。
新建src/views/teprunner/plan/PlanResult.vue文件:
主路由用來展示計劃運行結果,子路由用來展示用例運行結果(包含了日誌輸出)。跳轉程式碼是:
和測試計劃主頁面方式一樣,用到了this.$router.push()
。
新建src/views/teprunner/plan/CaseResult.vue文件,內容和src/views/teprunner/case/CaseResult.vue文件基本一樣,區別在於現在不是用的彈出框,而是路由到子頁面了,可視區域更佳,體驗更棒。
小結
本文進一步完善了測試平台的功能,除了單條用例運行,還能批量用例運行(催更的小夥伴可以拉程式碼嘗試下哦)。其中有個新技術,前端通過localStorage來給不同組件之間傳遞數據,這樣就可以把彈出框做成了子路由頁面 ,然後很方便地點擊鏈接進入子頁面,點擊麵包屑導航返回上級頁面。這為fixtures和用例管理中的彈出框優化提供了參考。
參考資料: