天天看點

接口測試架構實戰(三) | APIObject 模式、原則與應用

本文節選自霍格沃玆測試學院内部教材,文末連結進階學習。

APIObject 模式與原則

在普通的接口自動化測試中,如果接口的參數,比如 url,headers 等傳參改變,或者測試用例的邏輯、斷言改變,那麼整個測試代碼都需要改變。APIObject 設計模式借鑒了 PageObject 的設計模式,可以實作一個優雅、強大的接口測試架構。

理念

APIObject 設計模式可以簡單分為 6 個子產品,分别是 API 對象、接口測試架構、配置子產品、資料封裝、Utils、測試用例。

  • 接口測試架構:base_api,完成對 API 的驅動
  • API 對象:繼承 base_api 後,完成對接口的封裝
  • 配置子產品:完成配置檔案的讀取
  • 資料封裝:資料構造與測試用例的資料封裝
  • Utils:其他功能封裝,改進原生架構不足
  • 測試用例:調用 Page/API 對象實作業務并斷言

枯燥的講述概念可能難以了解,後面的章節都會圍繞這個6個子產品進行理論的拆解和執行個體的示範。

APIObject 模式應用

本章将結合企業微信的部門管理,擷取部門清單接口作為一個接口測試用例,從沒有封裝到使用APIObject 設計模式進行封裝改造。将實戰與理論結合,更深入了解 APIObject 設計模式。

環境準備

企業微信服務端 API:

https://work.weixin.qq.com/api/doc/90000/90135/90664

不加任何封裝和改造的企業微信,擷取部門清單接口測試用例:

import requests


class TestDemo:

    def test_get_token(self):
        r = requests.get(url="https://qyapi.weixin.qq.com/cgi-bin/gettoken",
            params={"corpid": "ww93348658d7c66ef4", "corpsecret": "T0TFrXmGYel167lnkzEydsjl6bcDDeXVmkUnEYugKIw"})
        return r.json()["access_token"]

    def test_department_list(self):
        r = requests.get(url="https://qyapi.weixin.qq.com/cgi-bin/department/list",
            params={"access_token": self.test_get_token(), "id": 1})
        assert r.json()["errcode"] == 0
        return print(r.json())           
思路

改造後的檔案結構:

├── __init__.py
├── api
│   ├── __init__.py
│   ├── base_api.py
│   ├── department.py
│   └── wework.py
├── data
│   └── department_list.yml
├── testcases
│   ├── __init__.py
│   └── test_department_list.py
└── utils
    ├── __init__.py
    └── utils.py           
  • API
    * base_api.py 是封裝用來所有 API 的通用方法,比如列印 Log、對斷言工具做二次封裝等,不牽涉和業務相關的操作;           
    • wework.py 繼承 base_api 并實作基本業務,之後所有的具體的業務資源繼承自 wework,比如 token 的擷取等;
    • department 繼承自 wework,用來實作對應子產品具體的業務邏輯,比如發送請求,請求内有什麼參數等等。
  • testcases 檔案夾内統一存放所有的測試用例,調用 API 對象實作業務并斷言;
  • utils 檔案夾記憶體放對其他功能封裝,改進原生架構不足;
  • data 檔案夾資料構造與測試用例的資料封裝;

此外,還有配置子產品與資料封裝會在後面的章節進行具體的介紹。

APIObject 實戰

utils.py,在此檔案中封裝一個 jsonpath 方法。

import json

from jsonpath import jsonpath

class Utils:
    @classmethod
    def jsonpath(cls, json_object, expr):
        return jsonpath(json_object, expr)           

base_api.py,在此檔案中調用utils中的jsonpath方法。

from test_wework.utils.Utils import Utils

class BaseApi:
    json_data = None

    def jsonpath(self, expr):
        return Utils.jsonpath(self.json_data, expr)           

wework.py,繼承類

BaseApi

,實作 token 的擷取。将在後面“通用 API 封裝”章節中詳細講述函數内部的設計。

class WeWork(BaseApi):
    corpid = "ww93348658d7c66ef4"
    contact_secret = "T0TFrXmGYel167lnkzEydsjl6bcDDeXVmkUnEYugKIw"
    token = dict()
    token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"

    @classmethod
    def get_token(cls, secret=contact_secret):
        # 避免重複請求,提高速度
        if secret not in cls.token.keys():
            r = cls.get_access_token(secret)
            cls.token[secret] = r["access_token"]
        return cls.token[secret]

    @classmethod
    def get_access_token(cls, secret):
        r = requests.get(cls.token_url, params={"corpid": cls.corpid, "corpsecret": secret})
        return r.json()           

department.py,繼承類

WeWork

,發起一個 get 請求,擷取 department 的 list。

class Department(BaseApi):
    list_url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"

    def list(self, id):
        self.json_data = requests.get(self.list_url, params={"access_token": WeWork.get_contact_token(), "id": id}).json()
        return self.json_data           

test_department.py,斷言傳回值中的第一個 name 是否為"WestWayyt"。

class TestDepartment:
    department = Department()

    def test_department_list(self):
        r = self.department.list(1)
        assert self.department.jsonpath(expr="$..name")[0] == "WestWayyt"           

以上,更多接口測試架構實戰進階内容,我們在後續文章分享。

更多技術文章分享及測試資料