【软件测试】测试框架(unittest/pytest)
本文介绍了Python 中最常用的两个测试框架:unittest
和 pytest
,帮助你编写更规范、可维护的自动化测试用例。
一、unittest 框架
unittest
是 Python 内置的标准库,无需额外安装,适合初学者入门。它借鉴了 JUnit 的设计理念,提供了测试用例、测试套件、断言等基本功能。
1. 基本概念
- TestCase:测试用例的基类,每个测试方法必须以
test_
开头 - TestSuite:测试套件,用于组织多个测试用例
- TestRunner:测试运行器,执行测试并生成结果
- Assertion:断言,验证测试结果
2. 简单示例
下面是一个使用 unittest
测试登录功能的示例:
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import Byclass TestLogin(unittest.TestCase):def setUp(self):# 每个测试方法执行前运行,初始化浏览器self.driver = webdriver.Firefox()self.driver.get('https://example.com/login')self.driver.implicitly_wait(10)def tearDown(self):# 每个测试方法执行后运行,关闭浏览器self.driver.quit()def test_successful_login(self):# 测试成功登录的场景username = self.driver.find_element(By.ID, 'username')password = self.driver.find_element(By.ID, 'password')login_button = self.driver.find_element(By.ID, 'login-button')username.send_keys('valid_username')password.send_keys('valid_password')login_button.click()# 断言登录成功后页面上存在欢迎消息welcome_message = self.driver.find_element(By.CLASS_NAME, 'welcome-message')self.assertIn('欢迎', welcome_message.text)def test_failed_login(self):# 测试失败登录的场景username = self.driver.find_element(By.ID, 'username')password = self.driver.find_element(By.ID, 'password')login_button = self.driver.find_element(By.ID, 'login-button')username.send_keys('invalid_username')password.send_keys('invalid_password')login_button.click()# 断言错误消息存在error_message = self.driver.find_element(By.CLASS_NAME, 'error-message')self.assertIn('用户名或密码错误', error_message.text)if __name__ == '__main__':unittest.main()
3. 常用断言方法
断言方法 | 作用 |
---|---|
assertEqual(a, b) | 验证 a == b |
assertNotEqual(a, b) | 验证 a != b |
assertTrue(x) | 验证 x 为 True |
assertFalse(x) | 验证 x 为 False |
assertIn(a, b) | 验证 a 在 b 中 |
assertNotIn(a, b) | 验证 a 不在 b 中 |
assertIsNone(x) | 验证 x 为 None |
assertIsNotNone(x) | 验证 x 不为 None |
二、pytest 框架
pytest
是第三方测试框架,功能更强大,插件丰富,语法更简洁,是目前最流行的 Python 测试框架。
1. 安装
pip install pytest
2. 基本概念
- 测试函数:以
test_
开头的普通函数 - 测试类:以
Test
开头的类,其中的方法以test_
开头 - fixture:用于测试环境的初始化和清理
- 参数化测试:一次编写,多次执行不同参数的测试
3. 简单示例
下面是使用 pytest
和 fixture
实现的登录测试:
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By@pytest.fixture
def browser():# 初始化浏览器driver = webdriver.Firefox()driver.implicitly_wait(10)yield driver # 返回driver给测试函数# 测试结束后关闭浏览器driver.quit()def test_successful_login(browser):browser.get('https://example.com/login')username = browser.find_element(By.ID, 'username')password = browser.find_element(By.ID, 'password')login_button = browser.find_element(By.ID, 'login-button')username.send_keys('valid_username')password.send_keys('valid_password')login_button.click()welcome_message = browser.find_element(By.CLASS_NAME, 'welcome-message')assert '欢迎' in welcome_message.textdef test_failed_login(browser):browser.get('https://example.com/login')username = browser.find_element(By.ID, 'username')password = browser.find_element(By.ID, 'password')login_button = browser.find_element(By.ID, 'login-button')username.send_keys('invalid_username')password.send_keys('invalid_password')login_button.click()error_message = browser.find_element(By.CLASS_NAME, 'error-message')assert '用户名或密码错误' in error_message.text
4. 参数化测试
pytest
最强大的功能之一是参数化测试,可以使用 @pytest.mark.parametrize
装饰器:
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By@pytest.fixture
def browser():driver = webdriver.Firefox()yield driverdriver.quit()@pytest.mark.parametrize("username, password, expected_message",[("valid_user1", "valid_pass1", "欢迎"), # 测试用例1("valid_user2", "valid_pass2", "欢迎"), # 测试用例2("invalid_user", "wrong_password", "用户名或密码错误"), # 测试用例3]
)
def test_login_parameterized(browser, username, password, expected_message):browser.get('https://example.com/login')username_field = browser.find_element(By.ID, 'username')password_field = browser.find_element(By.ID, 'password')login_button = browser.find_element(By.ID, 'login-button')username_field.send_keys(username)password_field.send_keys(password)login_button.click()if "valid" in username:message = browser.find_element(By.CLASS_NAME, 'welcome-message').textelse:message = browser.find_element(By.CLASS_NAME, 'error-message').textassert expected_message in message
5. 运行测试
在终端中执行测试:
# 运行当前目录下所有以test_开头的文件
pytest# 运行指定文件
pytest test_login.py# 显示详细输出
pytest -v# 生成HTML测试报告
pytest --html=report.html
三、unittest vs pytest 对比
特性 | unittest | pytest |
---|---|---|
断言方式 | 内置断言方法 | 使用 Python 原生 assert 语句 |
测试发现 | 基于类和方法命名规则 | 更灵活,支持更多命名模式 |
参数化测试 | 需要使用第三方库 | 内置参数化功能 |
测试夹具 | setUp/tearDown 方法 | 灵活的 fixture 机制 |
插件生态 | 较少 | 丰富的插件(如测试报告、并行执行) |
代码简洁度 | 较繁琐 | 简洁易读 |
四、推荐实践
- 使用 pytest:对于大多数项目,推荐使用
pytest
,它的灵活性和丰富插件能大大提高效率 - 合理使用 fixture:将浏览器初始化、登录等操作封装到 fixture 中,避免代码重复
- 参数化测试:使用参数化覆盖多种测试场景,减少代码量
- 生成测试报告:使用
pytest-html
或allure-pytest
生成美观的测试报告
相关文章:
【软件测试】测试框架(unittest/pytest)
本文介绍了Python 中最常用的两个测试框架:unittest 和 pytest,帮助你编写更规范、可维护的自动化测试用例。 一、unittest 框架 unittest 是 Python 内置的标准库,无需额外安装,适合初学者入门。它借鉴了 JUnit 的设计理念&…...
Kotlin 中 companion object 扩展函数详解
companion object 的扩展函数是 Kotlin 中一个强大但稍显复杂的特性,它允许你为类的伴随对象添加新的函数。下面我会通过清晰的示例和解释帮助你理解这个概念。 基本概念 扩展函数允许你为已有的类添加新函数,而无需继承或修改原始类。当这个扩展函数是…...
MySQL半同步复制配置和参数详解
目录 1 成功配置主从复制 2 加载插件 3 半同步复制监控 4 半同步复制参数 1 成功配置主从复制 操作步骤参考:https://blog.csdn.net/zyb378747350/article/details/148309545 2 加载插件 #主库上 MySQL 8.0.26 之前版本: mysql>INSTALL PLUGIN rpl_semi_syn…...
使用FastAPI构建车牌检测识别服务
概述 FastAPI FastAPI是一个现代的高性能 Web 框架,用于使用 Python 构建 API。它可以让开发者轻松快速高效地构建 API,同时提供 API 的自动验证、序列化和文档记录等功能,是构建 Web 服务和微服务的热门选择。 YOLO YOLO(YOLO(You Only Look Once)是一种流行的物体检…...

pikachu通关教程-File Inclusion
文件包含漏洞 本地文件包含 http://127.0.0.1:1000/pikachu/vul/fileinclude/fi_local.php?filenamefile1.php&submit%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2 首先我们把file1改成file2,发现切换成功 那我们可不可以上传本地文件呢,答案是肯定的&a…...
CppCon 2014 学习:Defensive Programming Done Right.
这段摘要讲的是: 在组件化开发中,每个开发者负责让自己写的软件易懂且好用,且不易被误用。常见误用之一是调用库函数时未满足前置条件,导致未定义行为。未定义行为的契约(contract)不一定不好,…...

《机器学习数学基础》补充资料:韩信点兵与拉格朗日插值法
本文作者:卓永鸿 19世纪的伟大数学家高斯,他对自己做的数学有非常高的要求,未臻完美不轻易发表。于是经常有这样的情况:其他也很厉害的数学家提出自己的工作,高斯便拿出自己的文章说他一二十年前就做出来了࿰…...

Spring Boot中保存前端上传的图片
在Spring Boot中保存前端上传的图片可以通过以下步骤实现: 1. 添加依赖 确保在pom.xml中已包含Spring Web依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifact…...
【HTML-15.2】HTML表单按钮全面指南:从基础到高级实践
表单按钮是网页交互的核心元素,作为用户提交数据、触发操作的主要途径,其重要性不言而喻。本文将系统性地介绍HTML表单按钮的各种类型、使用场景、最佳实践以及高级技巧,帮助开发者构建更高效、更易用的表单交互体验。 1. 基础按钮类型 1.1…...

2025最新 MacBook Pro苹果电脑M系列芯片安装zsh教程方法大全
2025最新 MacBook Pro苹果电脑M系列芯片安装zsh教程方法大全 本文面向对 macOS 环境和终端操作尚不熟悉的“小白”用户。我们将从最基础的概念讲起,结合实际操作步骤,帮助你在 2025 年最新 MacBook Pro(搭载苹果 M 系列芯片)的环境…...
43. 远程分布式测试实现
43. 远程分布式测试实现详解 一、远程测试环境配置 1.1 远程WebDriver服务定义 # Chrome浏览器远程服务地址 chrome_url rhttp://localhost:5143# Edge浏览器远程服务地址 edge_url rhttp://localhost:9438关键概念:每个URL对应一个独立的WebDriver服务典型配置…...
探索大语言模型(LLM):RSE流程详解——从文档中精准识别高相关片段
前言 在信息爆炸的时代,如何从海量的文本数据中快速准确地提取出有价值的信息,成为了众多领域面临的共同挑战。RSE(检索增强摘要生成)流程应运而生,它通过一系列精细化的步骤,能够有效地从原始文档中识别出…...
【C++】类的构造函数
类的构造函数 1. 作用:2.语法规则:示例代码:构造函数语法 2.1 特点:示例代码:自定义了构造函数,系统不会再生成默认构造函数示例代码:构造函数重载 3.构造函数常见的写法3.1 无参构造函数3.2 带…...

【ISP算法精粹】动手实战:用 Python 实现 Bayer 图像的黑电平校正
在数字成像领域,图像信号处理器(ISP)如同幕后英雄,默默将传感器捕获的原始数据转化为精美的图像。而黑电平校正,作为ISP预处理流程中的关键一环,直接影响着最终图像的质量。今天,我们就通过Pyth…...
分布式存储技术全景解析:从架构演进到场景实践
目录 技术演进与市场新格局核心架构设计深度剖析前沿技术创新与性能突破行业应用场景实践挑战与未来发展趋势1. 技术演进与市场新格局 1.1 从集中式到分布式的范式转移 传统集中式存储(如NAS/SAN)在扩展性和容错性方面面临根本性瓶颈,而分布式存储通过水平扩展架构和多节点…...
JVM——从JIT到AOT:JVM编译器的云原生演进之路
引入 在Java的世界里,一段代码从开发者手中的文本到计算机执行的机器指令,需要跨越"字节码"这座桥梁。而JVM编译器正是架起这座桥梁的工程师,它的每一次技术演进都推动着Java性能的跃迁。从早期逐行翻译的解释器,到智能…...

Linux中的mysql逻辑备份与恢复
一、安装mysql社区服务 二、数据库的介绍 三、备份类型和备份工具 一、安装mysql社区服务 这是小编自己写的,没有安装的去看看 Linux换源以及yum安装nginx和mysql-CSDN博客 二、数据库的介绍 2.1 数据库的组成 数据库是一堆物理文件的集合,主要包括…...

[HTML5]快速掌握canvas
背景 canvas 是 html5 标准中提供的一个标签, 顾名思义是定义在浏览器上的画布 通过其强大的绘图接口,我们可以实现各种各样的图形,炫酷的动画,甚至可以利用他开发小游戏,包括市面上很流行的数据可视化框架底层都用到了Canvas。…...

Gartner《Emerging Patterns for Building LLM-Based AIAgents》学习心得
一、AI代理概述 2024年,AI代理成为市场热点,它们能自主规划和行动以实现用户目标,与仅能感知、决策、行动和达成目标的AI助手及聊天机器人有本质区别。Gartner定义的AI代理是使用AI技术在数字或物理环境中自主或半自主运行的软件实体。 二、LLM基础AI代理的特性和挑战 优势…...
Hive SQL优化实践:提升大数据处理效率的关键策略
在大数据生态中,Hive作为基于Hadoop的数据仓库工具,广泛应用于海量数据的离线分析场景。然而,随着数据量的指数级增长和业务复杂度的提升,低效的Hive SQL可能导致资源浪费和查询性能瓶颈。本文将从存储优化、计算优化、资源配置三…...
vue中父子参数传递双向的方式不同
在面试中被问到。平时也有用到,但是缺少总结 父传子。父页面会给子页面中定义的props属性传参,子页面接收子传父。父页面需要监听事件来接收子页面通过$emit发送的消息其实说的以上两种都是组件之间传递。还可以通过路由传参, 状态管理器的方式传递 下面…...
LLM 使用 MCP 协议及其原理详解
LLM 使用 MCP 协议及其原理详解 🧠 一、MCP 协议概述 1. MCP 是什么? MCP(Modular Communication Protocol)是一种面向语言模型设计的通用通信协议,其设计目标是: 模块化(Modular࿰…...
DAY 36神经网络加速器easy
仔细回顾一下神经网络到目前的内容,没跟上进度的同学补一下进度。 ●作业:对之前的信贷项目,利用神经网络训练下,尝试用到目前的知识点让代码更加规范和美观。 ●探索性作业(随意完成):尝试进入…...

STM32 单片机启动过程全解析:从上电到主函数的旅程
一、为什么要理解启动过程? STM32 的启动过程就像一台精密仪器的开机自检,它确保所有系统部件按既定方式初始化,才能顺利运行我们的应用代码。对初学者而言,理解启动过程能帮助解决常见“程序跑飞”“不进 main”“下载后无反应”…...

4.RV1126-OPENCV 图像轮廓识别
一.图像识别API 1.图像识别作用 它常用于视觉任务、目标检测、图像分割等等。在 OPENCV 中通常使用 Canny 函数、findContours 函数、drawContours 函数结合在一起去做轮廓的形检测。 2.常用的API findContours 函数:用于寻找图片的轮廓,并把所有的数…...

WEB3——开发者怎么查看自己的合约日志记录
在区块链中查看合约的日志信息(也叫事件 logs),主要有以下几种方式,具体方法依赖于你使用的区块链平台(如 Ethereum、BSC、Polygon 等)和工具(如 Etherscan、web3.js、ethers.js、Hardhat 等&am…...

TDengine 集群容错与灾备
简介 为了防止数据丢失、误删操作,TDengine 提供全面的数据备份、恢复、容错、异地数据实时同步等功能,以保证数据存储的安全。本节简要说明 TDengine 中的容错与灾备。 容错 TDengine 支持 WAL 机制,实现数据的容错能力,保证数…...

MG影视登录解锁永久VIP会员 v8.0 支持手机电视TV版影视直播软件
MG影视登录解锁永久VIP会员 v8.0 支持手机电视TV版影视直播软件 MG影视App电视版是一款资源丰富、免费便捷、且专为大屏优化的影视聚合应用,聚合海量资源,畅享电视直播,是您电视盒子和…...
如何成为一名优秀的产品经理(自动驾驶)
一、 夯实核心基础 深入理解智能驾驶技术栈: 感知: 摄像头、雷达(毫米波、激光雷达)、超声波传感器的工作原理、优缺点、融合策略。了解目标检测、跟踪、SLAM等基础算法概念。 定位: GNSS、IMU、高精地图、轮速计等定…...
BAT脚本编写详细教程
目录 第一部分:BAT脚本简介第二部分:创建和运行BAT脚本第三部分:基本命令和语法第四部分:变量使用第五部分:流程控制第六部分:函数和子程序第七部分:高级技巧第八部分:实用示例第一部分:BAT脚本简介 BAT脚本(批处理脚本)是Windows操作系统中的一种脚本文件,扩展名…...