本章主要以【企业微信】为例讲述api自动化框架搭建
ps:有空再将代码会上传到github
以前也写过类似简单的接口自动化测试搭建:
如下参考链接:
apis
-base包:封装api的基础类
-contract包:封装组织的所有api
data包:参数化数据(excel 或者 yml...)
logs包:日志文件
testcase包:封装测试用例类
utils包:工具包,例如读取参数化数据
"""
该类为api测试框架的基类
可以封装框架本身的东西,例如:request
"""
import requests
from mikasa_script.mikasa_auto.workwx_api_autotest.utils.log_utils import logger
class BaseApi:
def send_api(self, req, tools="requests"):
"""
对发送接口测试的工具进行封装(可以使用urlib3/requests)
:param tools:
:param req:
:return:
"""
# 如果没有发送工具,则默认使用requests
# if not tools:
# tools = "requests"
logger.info(f"获取到的工具为:{tools}")
logger.info(f"获取到的接口发送的数据为:{req}")
if tools == "requests":
return requests.request(**req)
"""
该类为企业微信api类
这里可以封装针对企业微信的一些常用方法
"""
from mikasa_script.mikasa_auto.workwx_api_autotest.apis.base.base_api import BaseApi
class WorkWxApi(BaseApi):
def __init__(self):
self.token = None
def get_token(self, corpid, corpsecret):
"""
获取企业微信accesss_token
:param corpid: 企业微信后台,我的企业可以找到
:param corpsecret: 企业微信后台,管理工具—通讯录同步可以获取到
:return:
"""
req = {
"method": "GET",
"url": "https://qyapi.weixin.qq.com/cgi-bin/gettoken",
"params": {
"corpid": corpid,
"corpsecret": corpsecret
}
}
res = self.send_api(req)
self.token = res.json()["access_token"]
print("获取到的accessToken:", self.token)
return self.token
"""
具体业务类:
该类为企业微信,部门相关接口类
注意:所有的具体业务类,需全部继承自WorkWxApi类
"""
from mikasa_script.mikasa_auto.workwx_api_autotest.apis.base.workwx_api import WorkWxApi
from mikasa_script.mikasa_auto.workwx_api_autotest.utils.utils import Utils
class Department(WorkWxApi):
def __init__(self):
# 获取到yaml文件里的数据,传参调用get_token
yaml_data = Utils.get_yaml_data("/corp_data.yaml")
self.get_token(yaml_data.get("corpid").get("mikasa"), yaml_data.get("secret").get("department"))
def create_department(self, _id):
"""
创建部门
:return:
"""
req = {
"method": "POST",
"url": "https://qyapi.weixin.qq.com/cgi-bin/department/create",
"params": {
"access_token": self.token
},
"json": {
"name": f"mikasa部门_创建{_id}",
"name_en": f"mikasa_create_{_id}",
"parentid": 1,
"order": 1,
"id": _id
}
}
res = self.send_api(req)
print("创建部门:", res.json())
return res.json()
def update_department(self, _id):
"""
修改部门
:return:
"""
req = {
"method": "POST",
"url": "https://qyapi.weixin.qq.com/cgi-bin/department/update",
"params": {
"access_token": self.token
},
"json": {
"name": f"mikasa部门{_id}",
"name_en": f"mikasa_create_{_id}",
"parentid": 1,
"order": 1,
"id": _id
}
}
res = self.send_api(req)
return res.json()
def get_department(self):
"""
获取部门
:return:
"""
req = {
"method": "GET",
"url": "https://qyapi.weixin.qq.com/cgi-bin/department/list",
"params": {
"access_token": self.token
}
}
res = self.send_api(req)
print(res.json())
return res.json()
def del_department(self, _id):
"""
删除部门
:return:
"""
req = {
"method": "GET",
"url": "https://qyapi.weixin.qq.com/cgi-bin/department/delete",
"params": {
"access_token": self.token,
"id": _id
}
}
res = self.send_api(req)
return res.json()
if __name__ == '__main__':
# Department().create_department(2)
# Department().update_department(2)
Department().get_department()
# Department().del_department(2)
corpid:
mikasa: ww0da7c2c6dbb1d65f
secret:
department: NHkyn5X__aQTidlgH1fJbNtoAxyj1Nv_b9fwW8tnbuc
"""
该类为工具类
包括读取yaml文件/读取log日志文件路径
"""
import os
import jsonpath
import yaml
class Utils:
@classmethod
def get_yaml_data(self, yaml_file):
"""
封装提取yaml文件的方法
:param yaml_file: 传入文件的路径
:return:
"""
with open(f"{Utils.get_data_path()}/{yaml_file}", encoding="utf-8") as f:
datas = yaml.safe_load(f)
return datas
@classmethod
def get_data_path(self):
"""
获取data文件路径
:return:
"""
path = os.sep.join([os.path.dirname(os.path.abspath(__file__)), "../data"])
print("path", path)
return path
@classmethod
def get_log_path(cls):
"""
获取日志文件路径
:return:
"""
path = os.sep.join([os.path.dirname(os.path.abspath(__file__)), "../logs"])
print("path", path)
return path
@classmethod
def jsonpath_utils(cls, obj, expt):
"""
json处理工具
:param obj:
:param expt:
:return:
"""
return jsonpath.jsonpath(obj, expt)
if __name__ == '__main__':
path = Utils.get_data_path()
print(Utils.get_yaml_data("/corp_data.yaml"))
"""
该类为日志封装类
"""
import logging
import os
# 实例化logger对象
from mikasa_script.mikasa_auto.workwx_api_autotest.utils.utils import Utils
logger = logging.getLogger(__name__)
# 定义日志文件路径
log_path = Utils.get_log_path()
# 判断路径是否存在,不存在就创建
if not os.path.exists(log_path):
os.mkdir(log_path)
# 绑定log的handler
file_handler = logging.FileHandler(filename=f"{log_path}/api_object.log", encoding="utf-8")
# 输出的formatter
formatter = logging.Formatter(
'[%(asctime).19s] %(process)d%(levelname).1s %(filename)s:%(lineno)d:%(funcName)s: %(message)s]')
# 日志格式与句柄的绑定
file_handler.setFormatter(formatter)
# 控制台句柄定义
steam_handler = logging.StreamHandler()
# 日志格式与句柄的绑定
steam_handler.setFormatter(formatter)
# 与logging进行绑定
logger.addHandler(file_handler)
logger.addHandler(steam_handler)
# 设置展示/写入文件的日志的级别
logger.setLevel(logging.INFO)
"""
该类为企业微信的部门相关接口的测试用例类
"""
import allure
from mikasa_script.mikasa_auto.workwx_api_autotest.apis.contract.department import Department
from mikasa_script.mikasa_auto.workwx_api_autotest.utils.log_utils import logger
from mikasa_script.mikasa_auto.workwx_api_autotest.utils.utils import Utils
@allure.feature('test_department')
class TestDepartment:
def setup(self):
self.department_id = 1
self.depart = Department()
try:
self.depart.del_department(self.department_id)
except Exception as e:
logger.warning("没有待删除的部门")
def teardown(self):
pass
def setupclass(self):
pass
def teardownclass(self):
pass
@allure.story('test_create_department')
def test_create_department(self):
assert self.depart.create_department(self.department_id)["errcode"] == 0
# logger.info(self.depart.get_department())
obj = self.depart.get_department()
department_list = Utils.jsonpath_utils(obj, "$..department..id")
assert self.department_id in department_list
# terminal执行allure命令:
pytest test_lover_pad.py --alluredir=./result --clean-alluredir #生成result文件
allure serve ./result #生成报告