当前位置: 首页 > news >正文

自动化测试实战—petstore实战

补充:环境配置

# 配置日志
import logging
import osfrom logging.handlers import RotatingFileHandler# 绑定绑定句柄到logger对象
logger = logging.getLogger(__name__)
# 获取当前工具文件所在的路径
root_path = os.path.dirname(os.path.abspath(__file__))
# 拼接当前要输出日志的路径
log_dir_path = os.sep.join([root_path, '..', f'/logs'])
if not os.path.isdir(log_dir_path):os.mkdir(log_dir_path)
# 创建日志记录器,指明日志保存路径,每个日志的大小,保存日志的上限
file_log_handler = RotatingFileHandler(os.sep.join([log_dir_path, 'log.log']), maxBytes=1024 * 1024, backupCount=10)
# 设置日志的格式
date_string = '%Y-%m-%d %H:%M:%S'
formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] [%(filename)s]/[line: %(lineno)d]/[%(funcName)s] %(message)s ', date_string)
# 日志输出到控制台的句柄
stream_handler = logging.StreamHandler()
# 将日志记录器指定日志的格式
file_log_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)
# 为全局的日志工具对象添加日志记录器
# 绑定绑定句柄到logger对象
logger.addHandler(stream_handler)
logger.addHandler(file_log_handler)
# 设置日志输出级别

 

 一、单个接口冒烟用例完成

import requestsfrom pet_shop.utils.log_utils import loggerclass TestPetstoreSearch:'''宠物商店宠物查询单接口测试,冒烟'''def setup_class(self):self.base_url="https://petstore.swagger.io/v2/pet"#拼接宠物查询接口self.search_url = self.base_url+"/findByStatus"def test_search_pet(self):#宠物查询接口请求参数pet_status={"status":"available"}#发出查询接口请求r=requests.get(self.search_url,params=pet_status)#打印响应结果,t添加日志logger.info(r.text)#断言响应状态码为200assert r.status_code==200#断言响应结果中包含可用状态的宠物assert r.json()!= []#响应反回来的是一个数组,数组中每个对象都包含id'字段assert "id" in r.json()[0]

二、多个接口冒烟测试

import pytest
import requests
from pet_shop.utils.log_utils import loggerclass TestPetstoreSearch:"""宠物商店宠物查询单接口测试,冒烟"""def setup_class(self):self.base_url = "https://petstore.swagger.io/v2/pet"self.search_url = self.base_url + "/findByStatus"@pytest.mark.parametrize("status",["available", "pending", "sold"],ids=["available_pets", "pending_pets", "sold_pets"])def test_search_pet_params(self, status):"""参数化测试:分别查询 available, pending, sold 状态的宠物"""pet_status = {"status": status  # 修复:这里应该是传入的参数 `status`,而不是字符串 "status"}r = requests.get(self.search_url, params=pet_status)logger.info(f"Response for status='{status}': {r.text}")assert r.status_code == 200assert r.json() != []  # 确保返回至少一个宠物assert "id" in r.json()[0]  # 第一个宠物包含 id 字段

 三、异常处理

1.测试用例设计

import pytest
import requests
from pet_shop.utils.log_utils import loggerclass TestPetstoreSearch:"""宠物商店宠物查询单接口测试,冒烟"""def setup_class(self):self.base_url = "https://petstore.swagger.io/v2/pet"self.search_url = self.base_url + "/findByStatus"@pytest.mark.parametrize("status",["available", "pending", "sold"],ids=["available_pets", "pending_pets", "sold_pets"])def test_search_pet_params(self, status):"""参数化测试:分别查询 available, pending, sold 状态的宠物"""pet_status = {"status": status  # 修复:这里应该是传入的参数 `status`,而不是字符串 "status"}r = requests.get(self.search_url, params=pet_status)logger.info(f"Response for status='{status}': {r.text}")assert r.status_code == 200assert r.json() != []  # 确保返回至少一个宠物assert "id" in r.json()[0]  # 第一个宠物包含 id 字段
#传入非指定状态数字,响应为空
#【异常】sraus 传入空字符串,响应为空
#不传入sarus,响应为空@pytest.mark.parametrize("status",["petstatus", "123456", ""],ids=["wrong_value", "number", "none_str"])def test_search_pet_failure(self,status):#查询异常pet_status = {"status": status  # 修复:这里应该是传入的参数 `status`,而不是字符串 "status"}r = requests.get(self.search_url, params=pet_status)logger.info(f"Response for status='{status}': {r.text}")assert r.status_code == 200assert r.json() == []  # 确保返回至少一个宠物

 

AssertionError: assert r.json() == [] 失败了

但实际返回的是一个包含多个宠物对象的列表,即使传入了一个无效的 status=""(空字符串)。

这个测试的初衷是:

“当传入非法或无效的 status 值时,期望接口返回空数组 [],表示没有匹配的宠物。”

但现实是:

  • 即使你传 status=""(空字符串),Swagger Petstore API 仍然返回了一些宠物,这些宠物的 "status": ""
  • 所以 r.json() != [],断言失败。

✅ 结论

Swagger Petstore 的 /pet/findByStatus 接口 并没有严格校验 status 参数是否为 "available", "pending", "sold" 之一。它会尝试模糊匹配,甚至对空字符串也会返回 status 字段为空的对象。

#不传入参数     def test_search_pet_none_param(self):r = requests.get(self.search_url,)logger.info(r.text)assert r.status_code == 200assert r.json() == [] def test_search_pet_wrong_param(self):pet_status = {"key": "available"  # 修复:这里应该是传入的参数 `status`,而不是字符串 "status"}r = requests.get(self.search_url, params=pet_status)logger.info(r.text)assert r.status_code == 200assert r.json() == []  # 确保返回至少一个宠

四、生成测试报告

环境:

  • 目的:生成可视化报告展示测试结果。
  • 操作:
  1. 安装依赖:pip install pytest allure-pytest
  2. 运行测试:pytest --alluredir=./allure-results
  3. 生成报告:allure serve ./allure-results
  • 报告效果:
  • 自动汇总通过/失败用例
  • 显示Bug细节(如除数为0的异常)
  • 图表展示用例覆盖率

 pytest -vs test_pet_search.py --alluredir=./report --clean-alluredir

参数说明:
pytest
调用 pytest 测试框架运行测试。

-v
以详细模式(verbose)运行测试,显示每个测试用例的执行结果。


-s
允许在控制台输出测试用例中的标准输出(如 print 或日志信息)。


test_pet_search.py
指定要运行的测试文件。


--alluredir=./report
指定 Allure 报告的生成目录为当前路径下的 report 文件夹。


--clean-alluredir
在生成 Allure 报告前清空指定的报告目录(./report)。

 

生成测试报告中出现一个错误 

❌ 问题 1:ModuleNotFoundError: No module named 'pet_shop'

test_pet_search.py 中写了:

from pet_shop.utils.log_utils import logger

这意味着 Python 会去 Python 的模块搜索路径(sys.path) 中找一个叫 pet_shop 的包。

但问题是:

  • pet_shop 是你的项目目录名,但它 不是一个被正确安装或加入到 Python 路径中的包
  • Python 并不知道 pet_shop 是一个模块,所以报错 No module named 'pet_shop'

✅ 解决方案

✅ 方法一:使用相对导入(推荐用于项目内部)

修改 test_pet_search.py 中的导入方式:

# 改成相对导入(如果 log_utils.py 在同级 utils 目录下)
from utils.log_utils import logger

所以下次要注意路径是否正确,以及尽量避免开头使用自建目录 

http://www.dtcms.com/a/305708.html

相关文章:

  • SparkSQL_数组排序函数 array_sort用法详解
  • 快秀录屏记录高光时刻,分享游戏激情
  • 少林寺用什么数据库?
  • 传统ERP迁移SAP Cloud ERP现代化升级:Kyano Crossway一种更智能的迁移方案
  • 【C++详解】深入解析多态 虚函数、虚函数重写、纯虚函数和抽象类、多态原理、重载/重写/隐藏的对⽐
  • Python字典高级映射:键到多值映射的工程实践
  • 智能Agent场景实战指南 Day 26:Agent评估与性能优化
  • SAP ABAP锁机制程序锁
  • LeetCode热题100--148. 排序链表--中等
  • Linux730 tr:-d /-s;sort:-r,-n,-R,-o,-t,-k,-u;bash;cut:-d,-c;tee -a;uniq -c -i
  • AD域设计与管理-批量创建域用户
  • 大语言模型API付费?
  • 【Qt】QTime::toString(“hh:mm:ss.zzz“) 显示乱码的原因与解决方案
  • MySQL EXPLAIN详解与高效调优方法
  • Spring-rabbit使用实战四
  • ConcurrentHashMapRedis实现二级缓存
  • 力扣219:存在重复元素Ⅱ
  • Android Animation Transitions:打造流畅的用户体验
  • 打造高效、安全的期货资管交易平台:开发流程与关键要素解析
  • VS Code中如何关闭Github Copilot
  • 为什么网站需要高防IP?高防IP的优势是什么?
  • android-PMS-创建新用户流程
  • CSS3 圆角
  • 【鸿蒙应用开发中,`signingConfigs` 用于配置应用签名的关键信息说明】
  • Vue.js 与后端技术结合开发指南
  • Python爬虫05_Requests肯德基餐厅位置爬取
  • jmeter读取上游接口并遍历数组数据并进行压测
  • Jmeter分布式测试
  • 【力扣热题100】哈希——字母异位词分组
  • Axure下拉菜单:从基础交互到高保真元件库应用