本文節選自霍格沃玆測試學院內部教材,文末鏈接進階學習。
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"
以上,更多接口測試框架實戰進階內容,我們在後續文章分享。