tep支持MVC架構實現用例數據分離

大家好,我是剛哥。

tep已經支持了兩種開發模式:用例數據一體和HttpRunner(第三版)。HttpRunner已經衆所周知,此處不做過多介紹。用例數據一體指的是把用例和數據都寫在一個test.py文件裏面,這樣的好處是簡單直接明瞭,特別適合剛開始用pytest寫自動化代碼的同學,從上往下一氣呵成就完成了一個自動化用例,收穫成就感的同時,也能很方便的共享給其他人使用,單個文件就能跑起來。

但是當我在公司用SpringBoot開發了一個後端服務後,嚐到了MVC架構所帶來的高可維護性,加上在跟各位大佬聊天時,也聽說很多公司對接口自動化做了分層設計,於是讓tep支持用例數據分離的開發,已經變得很重要了。用例數據分離指的是用例只有邏輯沒有數據,這樣在修改數據的時候,用例基本不需要變化就能適應,用例看起來是非常簡潔的,就像這樣:

class Test:
    case_vars = TepVars()
    case_vars.vars_ = {
        "domain": "http://127.0.0.1:5000",
        "skuNum": "3"
    }

    def test(self):
        # 登錄
        Login(Test).post()
        # 搜索商品
        SearchSku(Test).get()
        # 添加購物車
        AddCart(Test).post()
        # 下單
        Order(Test).post()
        # 支付
        Pay(Test).post()

這就是tep支持的用例數據分離的用例的樣子。

我增加了一個services文件夾,用於存放接口:

先看下登錄Login.py:

class Login(BaseRequest):

    def post(self):
        response = self.request(
            "post",
            url=self.case_vars.get("domain") + "/login",
            headers={"Content-Type": "application/json"},
            json={
                "username": "dongfanger",
                "password": "123456",
            }
        )
        assert response.status_code < 400
        self.case_vars.put("token", response.jmespath("token"))

  • 必須繼承BaseRequest。
  • self.request和requests.request用法完全一致。
  • self.case_vars用於在測試用例的測試步驟之間傳遞變量,有get和put兩個操作。
  • response.jmespath("token")是封裝了requests.Response後添加的方法,替代jmespath.search("token", response.json())的寫法。

BaseRequest的定義如下:

import jmespath
from requests import Response
from tep.client import request


class TepResponse(Response):
    def __init__(self, response):
        super().__init__()
        for k, v in response.__dict__.items():
            self.__dict__[k] = v

    def jmespath(self, expression):
        return jmespath.search(expression, self.json())


class BaseRequest:
    def __init__(self, clazz):
        self.case_vars = clazz.case_vars

    def request(self, method, url, **kwargs):
        response = request(method, url, **kwargs)
        return TepResponse(response)
  • TepResponse對requests.Response做了封裝,添加了jmespath方法。
  • BaseRequest的__init__在初始化時傳入測試類(test.py裏面測試用例的類),提取case_vars對象,這樣接口類繼承以後,就能用self.case_vars來get和put變量了。
  • 同時調用tep.client.request,並把response以封裝後的TepResponse返回。

那麼問題來了,如何在接口之間傳遞參數呢?請看test_login_pay_mvc.py、Login和SearchSku這三段代碼:

# test_login_pay_mvc.py

class Test:
    case_vars = TepVars()
    case_vars.vars_ = {
        "domain": "http://127.0.0.1:5000",
        "skuNum": "3"
    }

    def test(self):
        # 登錄
        Login(Test).post()
        # 搜索商品
        SearchSku(Test).get()
        # 添加購物車
        AddCart(Test).post()
        # 下單
        Order(Test).post()
        # 支付
        Pay(Test).post()
# Login.py

class Login(BaseRequest):

    def post(self):
        response = self.request(
            "post",
            url=self.case_vars.get("domain") + "/login",
            headers={"Content-Type": "application/json"},
            json={
                "username": "dongfanger",
                "password": "123456",
            }
        )
        assert response.status_code < 400
        self.case_vars.put("token", response.jmespath("token"))
# SearchSku.py

class SearchSku(BaseRequest):

    def get(self):
        response = self.request(
            "get",
            url=self.case_vars.get("domain") + "/searchSku",
            headers={"token": self.case_vars.get("token")},
            params={"skuName": "電子書"}
        )
        self.case_vars.put("skuId", response.jmespath("skuId"))
        self.case_vars.put("skuPrice", response.jmespath("price"))
        assert response.status_code < 400
  1. test_login_pay_mvc.py文件的Test測試用例裏面,定義了用例級別的變量:domain。
  2. Login.py文件通過self.case_vars.get("domain")獲取domain,然後把token通過self.case_vars.put("token", response.jmespath("token"))存入token。
  3. SearchSku.py文件通過self.case_vars.get("token")獲取token,並用self.case_vars.put()存入skuId和skuPrice,供下一個接口AddCart使用,以此類推。

用例數據分離的寫法遵從了MVC架構,並借鑑了HttpRunner和JMeter的部分設計,相比於用例數據一體,可能編寫體驗沒有那麼方便,但是維護性和可複用性都很高,其中接口類的get和post可以根據數據需要定義多個如get_a和post_b等,以支持多種數據,略微有一丟丟複雜,適合有代碼經驗的同學。

如何才能使用用例數據一體、用例數據分離、HttpRunner3種開發模式呢?等tep0.9.4版本發佈後進行升級,用tep startproject demo命令創建項目腳手架,就會包含登錄到下單流程的全部3種開發模式示例代碼,開箱即用,一鍵運行成功。

從此刻開始,tep實用性已經提升了一個檔次,但是我將停下它的腳步,將注意力放到HttpRunner3的源碼學習中,併產出一系列文章,站在巨人的肩膀上,才能看得更遠。爲什麼HttpRunner如此重要?因爲畢竟tep的技術就是從HttpRunner學來的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章