APIObject patterns and principles
In ordinary interface automation testing, if the parameters of the interface, such as url, headers, etc., change, or the logic and assertion of the test case change, then the entire test code needs to be changed. The APIObject design pattern borrows from PageObject's design pattern and can implement an elegant and powerful interface testing framework.
idea
The APIObject design pattern can be simply divided into 6 modules, which are API object, interface test framework, configuration module, data encapsulation, Utils, and test cases.
-
Interface testing framework: base_api, complete the API drive
-
API object: After inheriting base_api, complete the encapsulation of the interface
-
Configuration module: complete the reading of the configuration file
-
Data encapsulation: data encapsulation of data structure and test cases
-
Utils: Other function encapsulation, insufficient improvement of native framework
-
Test case: call Page/API object to implement business and assert
The boring presentation of concepts may be difficult to understand, and the following chapters will focus on the theoretical disassembly and demonstration of examples of these 6 modules.
APIObject mode application
This chapter will combine the department management of the enterprise WeChat to obtain the department list interface as an interface test case, from no encapsulation to the use of APIObject design pattern for encapsulation transformation. Combine actual combat with theory to gain a deeper understanding of the APIObject design pattern.
Environmental preparation
Enterprise WeChat server API:
https://work.weixin.qq.com/api/doc/90000/90135/90664
Without any encapsulation and transformation of enterprise WeChat, get the department list interface test case:
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())
Ideas
File structure after transformation:
├── __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 is a common method for encapsulating all APIs, such as printing Log, re-encapsulating the assertion tool, etc., without involving business-related operations;
-
wework.py inherits base_api and implements basic business. After that, all specific business resources are inherited from wework, such as token acquisition;
-
Department inherits from wework and is used to implement the specific business logic of the corresponding module, such as sending a request, what parameters are in the request, and so on.
-
-
All test cases are stored uniformly in the testcases folder, and API objects are called to implement business and assert;
-
The utils folder stores other function packages, which improves the lack of native framework;
-
Data folder data structure and data encapsulation of test cases;
In addition, there are configuration modules and data encapsulation that will be specifically introduced in the following chapters.
APIObject combat
utils.py, encapsulate a jsonpath method in this file.
import json
from jsonpath import jsonpath
class Utils:
@classmethod
def jsonpath(cls, json_object, expr):
return jsonpath(json_object, expr)
base_api.py, call the jsonpath
method in utils in this file .
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, inherited class BaseApi
, to achieve token acquisition. The internal design of the function will be described in detail in the chapter "General API Encapsulation".
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, an inherited class WeWork
, initiates a get request to get the list of department.
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, assert whether the first name in the return value is "WestWayyt".
class TestDepartment:
department = Department()
def test_department_list(self):
r = self.department.list(1)
assert self.department.jsonpath(expr="$..name")[0] == "WestWayyt"
Above, more advanced content of interface testing framework actual combat, we will share in follow-up articles. Pay attention to the " Programmer Two Black " official account to get more test and development dry goods content.