接口测试Day11-代码优化、生成测试报告、日志收集、全量字段校验

server/2025/2/7 23:19:48/
  • 获取请求头

1、. 在 common/ 下 创建 get_header.py 文件
2. 在 文件内 创建 get_header() 函数,实现 登录成功,获取令牌,拼接成 请求头,返回。
3. 在 scripts/ 的测试脚本文件中,添加 setUpClass 方法,调用 get_header() 函数。 将返回值 保存到 类属性上
4. 在 使用 请求头的位置,直接从类属性获取


# 在 common/ 下 创建 get_header.py 文件 实现 get_header 函数import requestsdef get_header():url = "http://ihrm-test.itheima.net/api/sys/login"data = {"mobile": "13800000002", "password": "123456"}resp = requests.post(url=url, json=data)print(resp.json())# 从 响应体中,获取 data的值token = resp.json().get("data")header = {"Content-Type": "application/json","Authorization": "Bearer " + token}return header----------------------------
# 在 scripts/ 的测试脚本文件中,添加 setUpClass 方法,调用 get_header 函数。 将返回值 保存到 类属性上
from common.get_header import get_headerclass TestEmpAdd(unittest.TestCase):# 类属性header = None@classmethoddef setUpClass(cls) -> None:cls.header = get_header()----------------------------
# 在 使用 请求头的位置,直接从类属性获取
resp = IhrmEmpCURD.add_emp(self.header, json_data)
  • 提取项目目录

相关知识:
__file__ : 获取 当前文件的 绝对路径。
BASE_DIR = os.path.dirname(__file__) : 获取 到 当前文件的 上一级目录。
此行代码,写在 config.py 中, 可以直接获取 项目目录

  • 项目中使用
  1. 在 config.py 文件中,添加 获取项目路径 全局变量 BASE_DIR = os.path.dirname(file)
  2. 修改 common/ 下 read_json_util.py 文件中,读取 json 文件 函数read_json_data(),添加 参数path_filename
  3. 在 使用 read_json_data()函数 时, 拼接 json 文件路径, 传入到 函数中
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

生成测试报告

步骤:

  1. 创建测试套件实例。 suite
  2. 添加 测试类
  3. 创建 HTMLTestReport 类实例。 runner
  4. runner 调用 run(), 传入 suite
import unittest
from config import BASE_DIR
from scripts.test_emp_add_params import TestEmpAddParams
from scripts.test_ihrm_login_params import TestIhrmLoginParams
from htmltestreport import HTMLTestReport# 1. 创建测试套件实例。 suite
suite = unittest.TestSuite()# 2. 添加 测试类, 组装测试用例
suite.addTest(unittest.makeSuite(TestIhrmLoginParams))
suite.addTest(unittest.makeSuite(TestEmpAddParams))# 3. 创建 HTMLTestReport 类实例。 runner
# runner = HTMLTestReport(BASE_DIR + "/report/ihrm.html") # 绝对路径
runner = HTMLTestReport("./report/ihrm.html", description="描述", title="标题") # 相对路径
# 4. runner 调用 run(), 传入 suite
runner.run(suite)
  • 日志收集

  • 日志简介

什么是日志
日志也叫 log,通常对应的 xxx.log 的日志文件。文件的作用是记录系统运行过程中,产生的信息。
搜集日志的作用
查看系统运行是否正常。
分析、定位 bug。

  • 日志的级别

logging.DEBUG:调试级别【高】
logging.INFO:信息级别【次高】
logging.WARNING:警告级别【中】
logging.ERROR:错误级别【低】
logging.CRITICAL:严重错误级别【极低】

在这里插入图片描述

  • 日志代码实现分析
    在这里插入图片描述
"""
步骤:
# 0. 导包
# 1. 创建日志器对象
# 2. 设置日志打印级别
# logging.DEBUG 调试级别
# logging.INFO 信息级别
# logging.WARNING 警告级别
# logging.ERROR 错误级别
# logging.CRITICAL 严重错误级别
# 3. 创建处理器对象
# 创建 输出到控制台 处理器对象
# 创建 输出到日志文件 处理器对象
# 4. 创建日志信息格式
# 5. 将日志信息格式设置给处理器
# 设置给 控制台处理器
# 设置给 日志文件处理器
# 6. 给日志器添加处理器
# 给日志对象 添加 控制台处理器
# 给日志对象 添加 日志文件处理器
# 7. 打印日志
"""
# 0. 导包
import logging
import logging.handlers
import time# 1. 创建日志器对象
logger = logging.getLogger()# 2. 设置日志打印级别
logger.setLevel(logging.DEBUG)
# logging.DEBUG 调试级别
# logging.INFO 信息级别
# logging.WARNING 警告级别
# logging.ERROR 错误级别
# logging.CRITICAL 严重错误级别# 3.1 创建 输出到控制台 处理器对象
st = logging.StreamHandler()# 3.2 创建 输出到日志文件 处理器对象
fh = logging.handlers.TimedRotatingFileHandler('a.log', when='midnight', interval=1,backupCount=3, encoding='utf-8')
# when 字符串,指定日志切分间隔时间的单位。midnight:凌晨:12点。
# interval 是间隔时间单位的个数,指等待多少个 when 后继续进行日志记录
# backupCount 是保留日志文件的个数# 4. 创建日志信息格式
fmt = "%(asctime)s %(levelname)s [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s"
formatter = logging.Formatter(fmt)# 5.1 日志信息格式 设置给 控制台处理器
st.setFormatter(formatter)
# 5.2 日志信息格式 设置给 日志文件处理器
fh.setFormatter(formatter)# 6.1 给日志器对象 添加 控制台处理器
logger.addHandler(st)
# 6.2 给日志器对象 添加 日志文件处理器
logger.addHandler(fh)# 7. 打印日志
# 运行每隔1s控制台打印除日志信息,控制台点击结束,目录下生成a.log文件
while True:# logging.debug('我是一个调试级别的日志')logging.info('我是一个信息级别的日志')# logging.warning('test log sh-26')# logging.error('我是一个错误级别的日志')# logging.critical('我是一个严重错误级别的日志')time.sleep(1)

日志的使用
在这里插入图片描述
在这里插入图片描述

"""
步骤:
# 0. 导包
# 1. 创建日志器对象
# 2. 设置日志打印级别
# logging.DEBUG 调试级别
# logging.INFO 信息级别
# logging.WARNING 警告级别
# logging.ERROR 错误级别
# logging.CRITICAL 严重错误级别
# 3. 创建处理器对象
# 创建 输出到控制台 处理器对象
# 创建 输出到日志文件 处理器对象
# 4. 创建日志信息格式
# 5. 将日志信息格式设置给处理器
# 设置给 控制台处理器
# 设置给 日志文件处理器
# 6. 给日志器添加处理器
# 给日志对象 添加 控制台处理器
# 给日志对象 添加 日志文件处理器
# 7. 打印日志
"""
# 0. 导包
import logging
import logging.handlers
import timedef init_log_config(filename, when='midnight', interval=1, backupCount=3):# 1. 创建日志器对象logger = logging.getLogger()# 2. 设置日志打印级别logger.setLevel(logging.DEBUG)# logging.DEBUG 调试级别# logging.INFO 信息级别# logging.WARNING 警告级别# logging.ERROR 错误级别# logging.CRITICAL 严重错误级别# 3.1 创建 输出到控制台 处理器对象st = logging.StreamHandler()# 3.2 创建 输出到日志文件 处理器对象fh = logging.handlers.TimedRotatingFileHandler(filename,when=when,interval=interval,backupCount=backupCount,encoding='utf-8')# when 字符串,指定日志切分间隔时间的单位。midnight:凌晨:12点。# interval 是间隔时间单位的个数,指等待多少个 when 后继续进行日志记录# backupCount 是保留日志文件的个数# 4. 创建日志信息格式fmt = "%(asctime)s %(levelname)s [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s"formatter = logging.Formatter(fmt)# 5.1 日志信息格式 设置给 控制台处理器st.setFormatter(formatter)# 5.2 日志信息格式 设置给 日志文件处理器fh.setFormatter(formatter)# 6.1 给日志器对象 添加 控制台处理器logger.addHandler(st)# 6.2 给日志器对象 添加 日志文件处理器logger.addHandler(fh)# # 7. 打印日志
# # 运行每隔1s控制台打印除日志信息,控制台点击结束,目录下生成a.log文件
# while True:
#     # logging.debug('我是一个调试级别的日志')
#     logging.info('我是一个信息级别的日志')
#     # logging.warning('test log sh-26')
#     # logging.error('我是一个错误级别的日志')
#     # logging.critical('我是一个严重错误级别的日志')
#     time.sleep(1)
if __name__ == '__main__':# 初始化日志init_log_config(filename='sh_26.log', interval=3, backupCount=5)# 打印出日志信息,如果步骤2日志打印级别设置成INFO,这部分就不会输出,按等级打印logging.debug('***---- debug日志信息查看')a = 100logging.info(f'日志信息测试 a={a}')

- [ ] List item

import logging
import unittestfrom apiTestFrameWork.api.classroom_system_api import ClassroomSystemAPI
from apiTestFrameWork.common.get_header import get_header
from apiTestFrameWork.logging_use import init_log_configclass TestClassroomSystem(unittest.TestCase):# 类属性header = Noneinit_log_config("codemao.log")@classmethoddef setUpClass(cls):cls.header = get_header()# 打印日志logging.debug(f'header={cls.header}')def test_getpackage_ok(self):# 在使用请求头的位置,直接从类属性获取headerresp_package_list = ClassroomSystemAPI.get_package(self.header)print(resp_package_list)logging.debug(f'课包列表 resp_package_list={resp_package_list}')
  • 全量字段校验
  • 简介和安装

概念:校验接口返回响应结果的全部字段(更进一步的断言)
校验内容:

  • 字段值
  • 字段名 或 字段类型

校验流程:

  • 定义json语法校验格式
  • 比对接口实际响应数据是否符合json校验格式

安装jsonschema:
pip install jsonschema -i https://pypi.douban.com/simple/

查验:

  • pip 查验:pip list 或 pip show jsonschema
  • pycharm 中 查验:file — settings — 项目名中查看 python解释器列表。
  • json Schema入门
    -在这里插入图片描述
# 2、创建 校验规则
schema = {"type": "object","properties": {"success": {"type": "boolean"},"code": {"type": "integer"},"message": {"type": "string"}},"required": ["success", "code", "message"]
}
  • 校验方式

在线工具校验:
http://json-schema-validator.herokuapp.com
https://www.jsonschemavalidator.net 【推荐】

在这里插入图片描述
在这里插入图片描述

实现步骤:
1 导包 import jsonschema
2 定义 jsonschema格式 数据校验规则
3 调用 jsonschema.validate(instance=“json数据”, schema=“jsonshema规则”)
查验校验结果:
校验通过:返回 None
校验失败:
schema 规则错误,返回 SchemaError
json 数据错误,返回 ValidationError

案例:

# 1、导包
import jsonschema# 2、创建 校验规则
schema = {"type": "object","properties": {"success": {"type": "boolean"},"code": {"type": "integer"# "type": "int"},"message": {"type": "string"}},"required": ["success", "code", "message"]
}
# 准备待校验数据
data = {"success": True,# "code": 10000,"code": "10000","message": "操作成功"
}
# 3、调用validate方法,实现校验
result = jsonschema.validate(instance=data, schema=schema)
print("result = ", result)# None:代表校验通过
# ValidationError: 数据 与 校验规则 不符
# SchemaError: 校验规则语法有误
# int和integer区别:int的默认值是0;integer的默认值是null
  • Json Schema语法
    在这里插入图片描述
  • type 关键字

作用:约束数据类型
integer —— 整数
string —— 字符串
object —— 对象
array —— 数组 --> python:list 列表
number —— 整数/小数
null —— 空值 --> python:None
boolean —— 布尔值
语法:
{
“type”: “数据类型”
}

示例:

import jsonschema# 准备校验规则
schema = {# "type": "number"# "type": "array"# "type": "null""type": "object"
}# 准备数据
# data = 100.1
# data = [1, 3, 4]
# data = None
data = {"a": 1, "b": 2}# 调用函数
result = jsonschema.validate(instance=data, schema=schema)
print(result)
  • properties 关键字

说明:是 type关键字的辅助。用于 type 的值为 object 的场景。
作用:指定 对象中 每个字段的校验规则。 可以嵌套使用。
在这里插入图片描述
在这里插入图片描述

import jsonschema# 创建校验规则
schema = {"type": "object","properties": {"success": {"type": "boolean"},"code": {"type": "integer"},"message": {"type": "string"},"money": {"type": "number"},"address": {"type": "null"},"data": {"type": "object"},"luckyNumber": {"type": "array"}}}
# 准备测试数据
data ={"success": True,"code": 10000,"message": "操作成功","money": 6.66,"address": None,"data": {"name": "tom"},"luckyNumber": [6, 8, 9]
}# 调用方法进行校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)

在这里插入图片描述

import jsonschema# 创建校验规则
schema = {"type": "object","properties": {"success": {"type": "boolean"},"code": {"type": "integer"},"message": {"type": "string"},"money": {"type": "number"},"address": {"type": "null"},"data": {"type": "object","properties": {                 # 对 data 的对象值,进一步进行校验"name": {"type": "string"},"age": {"type": "integer"},"height": {"type": "number"}}},"luckyNumber": {"type": "array"}}}
# 准备测试数据
data = {"success": True,"code": 10000,"message": "操作成功","money": 6.66,"address": None,"data": {"name": "tom","age": 18,"height": 1.78},"luckyNumber": [6, 8, 9]
}# 调用方法进行校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)
  • required关键字

作用:校验对象中必须存在的字段。字段名必须是字符串,且唯一
在这里插入图片描述

import jsonschema# 测试数据
data = {"success": True,"code": 10000,"message": "操作成功","data": None,
}# 校验规则
schema = {"type": "object","required": ["success", "code", "message", "data"]
}# 调用方法校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)
  • const 关键字

作用:校验字段值是一个固定值
在这里插入图片描述

import jsonschema# 测试数据
data = {"success": True,"code": 10000,"message": "操作成功","data": None,
}# 校验规则
schema = {"type": "object","properties": {"success": {"const": True},"code": {"const": 10000},"message": {"const": "操作成功"},"data": {"const": None}}
}# 调用方法校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)
  • pattern 关键字-正则简单语法

作用:指定正则表达式,对字符串进行模糊匹配
在这里插入图片描述
在这里插入图片描述

import jsonschema# 测试数据
data = {"message": "!jeklff37294操作成功43289hke","mobile": "15900000002"
}# 校验规则
schema = {"type": "object","properites":{"message": {"patten": "操作成功"},"mobile": {"patten": "^[0-9]{11}$"}}
}
# 调用方法校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)

综合案例:

import jsonschema# 测试数据
data = {"success": False,"code": 10000,"message": "xxx登录成功","data": {"age": 20,"name": "lily"}
}# 校验规则
schema = {"type": "object","properties": {"success": {"type": "boolean"},"code": {"type": "integer"},"message": {"patten": "登录成功$"},"data":{"type": "object","properties":{"age": {"const": 20},"name": {"const": "lily"}},"required": ["name", "age"]}},"required": ["success", "code", "message", "data"]
}# 调用方法校验
res = jsonschema.validate(instance=data, schema=schema)
print(res)

http://www.ppmy.cn/server/165791.html

相关文章

kakailio官网推荐的安装流程ubuntu 22.04

https://kamailio.org/docs/tutorials/6.0.x/kamailio-install-guide-git/ # 非必须项 wget -O- https://deb.kamailio.org/kamailiodebkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/kamailio.gpg在/etc/apt/sources.list文件追加以下内容 deb [signed-by/usr/sh…

Rust中使用ORM框架diesel报错问题

1 起初环境没有问题:在Rust开发的时候起初使用的是mingw64平台加stable-x86_64-pc-windows-gnu编译链,当使用到diesel时会报错,如下: x86_64-w64-mingw32/bin/ld.exe: cannot find -lmysql具体信息很长这是主要信息是rust找不到链…

14JavaWeb——SpringBoot原理

SpingBoot原理 在前面十多天的课程当中,我们学习的都是web开发的技术使用,都是面向应用层面的,我们学会了怎么样去用。而我们今天所要学习的是web后端开发的最后一个篇章springboot原理篇,主要偏向于底层原理。 我们今天的课程安…

解锁Spring Boot 3.1 + JDK 17:分布式系统的变革力量

分布式系统发展的现状与挑战 在当今数字化时代,分布式系统已成为互联网技术领域的核心支撑。从电商平台的海量交易处理,到社交网络的实时互动,再到金融领域的安全交易保障,分布式系统无处不在,它如同无形的纽带&#…

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之修改密码和个人资料

🧸安清h:个人主页 🎥个人专栏:【Spring篇】【计算机网络】【Mybatis篇】 🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。 目录 🎃1.修改密码 -持久…

手写单例模式

饿汉式加载模式(线程安全) 类一加载就创建对象,这种方式比较常用 优点:线程安全,没有加锁,执行效率高 缺点:不是懒加载,类初始化的时候就加载,浪费内存空间 package …

寒假2.5

题解 web:[网鼎杯 2020 朱雀组]phpweb 打开网址,一直在刷新,并有一段警告 翻译一下 查看源码 每隔五秒钟将会提交一次form1,index.php用post方式提交了两个参数func和p,func的值为date,p的值为Y-m-d h:i:s a 执行fu…

React Native 列表组件:FlashList、FlatList 及更多

在移动开发中,高效展示数据列表至关重要。作为 React Native 开发者,我们可以使用多种强大的工具来完成这一任务。无论是 ScrollView、SectionList 还是 FlatList,React Native 都提供了一系列用于数据展示的组件。 然而,随着数据…