測試平臺系列(74) 測試計劃定時執行初體驗

米洛丶發表於2021-11-15

大家好~我是米洛

我正在從0到1打造一個開源的介面測試平臺, 也在編寫一套與之對應的完整教程,希望大家多多支援。

歡迎關注我的公眾號測試開發坑貨,獲取最新文章教程!

回顧

上一節我們設計好了測試計劃表並編寫了CRUD介面,還沒來得及測試,我們就要馬不停蹄地編寫定時任務相關內容了。今天我們就來編寫一個完善的demo,可以定期執行測試計劃的用例,並生成報告。

至於後面的通知,要等到以後完善了。

調整Executor類裡面的部分方法

之前我們雖然支援了多條case非同步執行並寫入測試報告,但為了支援測試計劃,我們還需要進行一些調整。

  • 修改run_multiple方法

    我們的核心還是這個方法,因為裡面已經包裝好了執行多條case的方法。但我們要做一些改動:

變更引數

首先我們要調整它的引數,因為我們執行case的模式,有很多種,按照之前定義的mode欄位:

這個是測試報告表中定義的

調整一下

這樣,當我們呼叫run_mutiple方法的時候,就可以知道case的模式是什麼模式了,究竟是隸屬於測試計劃呢,還是屬於普通執行的case。我們調整一下,改成圖2的資料。

plan_id可以為空,如果有plan_id的話,可以直接跳轉到測試計劃相關頁面。方便編輯測試計劃,也方便排查問題。

ordered這個方法區分同步還是非同步,因為我們先前的run_multiple都是預設非同步的,但我們測試計劃又新增了同步模式,所以需要定義這樣一個引數

  • 修改ReportDao

也是新增這2個引數,透傳進來。方便報告裡面表明,這是什麼模式的執行,以及是否有測試計劃id。

  • 調整執行邏輯

根據ordered欄位判斷是否是同步執行,如果不是則和以前一致,是的話則用for的方式執行,保證用例執行的順序性

新增run_test_plan方法

    @staticmethod
    async def run_test_plan(plan_id: int):
        """
        通過測試計劃id執行測試計劃
        :param plan_id:
        :return:
        """
        plan = await PityTestPlanDao.query_test_plan(plan_id)
        if plan is None:
            Executor.log.info(f"測試計劃: [{plan_id}]不存在")
            return
        # 設定為running
        plan.state = 1
        await PityTestPlanDao.update_test_plan(plan, plan.update_user)
        # if plan.disabled:
        #     # 說明測試計劃已禁用
        #     Executor.log.info(f"測試計劃: [{plan.name}]未開啟")
        #     return
        env = list(map(int, plan.env.split(",")))
        case_list = list(map(int, plan.case_list.split(",")))
        await asyncio.gather(
            *(Executor.run_multiple(0, int(e), case_list, mode=1,
                                    plan_id=plan.id, ordered=plan.ordered) for e in env))
        # TODO 後續通知部分
        plan.state = 0
        await PityTestPlanDao.update_test_plan(plan, plan.update_user)

先通過query方法查到測試計劃資料,如果plan是None,說明沒有這個測試計劃,可能被刪掉了。

否則我們走執行邏輯: 根據plan的env欄位取出環境,並轉換為[1, 2]這樣的陣列。

這裡可能有點繞,因為我們資料庫存的env和case_list都是這樣的形式:

1,2,3,4

通過逗號分開,我們split以後,會得到: ["1", "2", "3", "4"]這樣的陣列,所以我們需要批量轉為int。

最後,由於一般環境之間會隔離,所以我們的ordered根據環境走就可以了,多環境執行我們可以按照非同步處理。

所以最後也選用了gather。

編寫Scheduler類

我們在utils目錄下新建scheduler.py檔案:

from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger

from app.utils.executor import Executor


class Scheduler(object):
    scheduler: AsyncIOScheduler = None

    @staticmethod
    def init(scheduler):
        Scheduler.scheduler = scheduler

    @staticmethod
    def configure(**kwargs):
        Scheduler.scheduler.configure(**kwargs)

    @staticmethod
    def start():
        Scheduler.scheduler.start()

    @staticmethod
    def add_test_plan(plan_id, plan_name, cron):
        return Scheduler.scheduler.add_job(func=Executor.run_test_plan, args=(plan_id,),
                                           name=plan_name, id=str(plan_id),
                                           trigger=CronTrigger.from_crontab(cron))

    @staticmethod
    def edit():
        pass

    @staticmethod
    def remove():
        pass

    @staticmethod
    def list():
        job_list = Scheduler.scheduler.get_jobs()
        return job_list

這裡我們對scheduler進行了非常簡單的封裝,然後定義了add_test_plan方法。

這個方法可以新增Executor.run_test_plan到定時任務,他接受id,name和cron3個引數,這個資料最終會落到定時任務表裡面去。

在新增測試計劃介面呼叫add_test_plan方法

當測試計劃新增成功的時候,我們自動新增定時任務

測試一下

FastApi深度結合了Swagger,所以我們只需要開啟: http://localhost:7777/docs便可以找到我們的測試方法:

填入token和測試計劃相關資訊即可

由於我已經新增過了,並且是每分鐘一次,所以我們只需要啟動服務,靜靜等待即可。

啟動服務的時候,提示我這個每分鐘執行的任務被miss了,我們再等一分鐘

可以看到,環境1和環境2保持每分鐘都在寫入測試報告到資料庫

那今天的簡單demo就完成到這裡,下一節我們完善刪改查的內容。

相關文章