软件测试基础十七(python Unittest)
Unittest
一、Unittest 简介
unittest
是 Python 内置的标准测试框架,用于编写和运行单元测试。它提供了一组工具和类,帮助开发者组织、编写和执行测试用例,以验证代码的正确性。
二、Unittest 核心要素
1. TestCase(测试用例类)
- 定义与作用:
-
TestCase
是unittest
框架中最小的测试单元,用于封装一个具体的测试场景。它通常是一个继承自unittest.TestCase
的类,每个类中的方法代表一个具体的测试用例。- 测试用例应该是独立的、可重复执行的,并且能够验证被测试代码的特定功能或行为。
- 主要方法:
例如:
import unittestclass TestCase(unittest.TestCase):def setUp(self):self.num = 5def tearDown(self):del self.numdef test_equal(self):self.assertEqual(self.num, 5)if __name__ == '__main__':unittest.main()
-
setUp()
:在每个测试方法执行之前被调用,用于设置测试环境,例如初始化对象、创建临时文件等。tearDown()
:在每个测试方法执行之后被调用,用于清理测试环境,例如删除临时文件、释放资源等。- 测试方法:以“test_”开头的方法被视为测试方法,这些方法中包含具体的测试逻辑和断言,用于验证被测试代码的输出是否符合预期。
2. TestSuite(测试套件)
- 定义与作用:
-
TestSuite
用于组合多个测试用例或测试套件,形成一个更大的测试集合。它可以将多个相关的测试用例组织在一起,方便一次性执行。- 通过
TestSuite
,可以灵活地选择要执行的测试用例,以及控制测试的执行顺序。
- 主要方法:
例如:
import unittestclass TestA(unittest.TestCase):def test_a(self):passclass TestB(unittest.TestCase):def test_b(self):passsuite = unittest.TestSuite()
suite.addTest(TestA('test_a'))
suite.addTest(TestB('test_b'))
-
addTest(test_case)
:将一个测试用例添加到测试套件中。addTests(test_cases)
:将多个测试用例添加到测试套件中。
3. TestRunner(测试运行器)
- 定义与作用:
-
TestRunner
负责执行测试用例或测试套件,并生成测试结果报告。它可以将测试结果以文本形式或其他格式输出,以便开发者查看测试的执行情况。- 不同的
TestRunner
可以提供不同的输出格式和功能,例如TextTestRunner
以文本形式输出测试结果,而一些第三方库可以生成 HTML 格式的测试报告。
- 主要方法:
例如:
import unittestsuite = unittest.TestSuite()
# 添加测试用例到套件
runner = unittest.TextTestRunner()
result = runner.run(suite)
-
run(test)
:执行给定的测试用例或测试套件,并返回一个TestResult
对象,其中包含测试的结果信息。
4. 示例代码:
4.1. 新建一个文件test01.py,用例如下:
import unittestdef sum_( a, b):return a + bclass TestA(unittest.TestCase):def test_add_1(self):result = sum_(1, 2)self.assertEqual(result, 3)def test_add_2(self):result = sum_(2, 3)self.assertNotEqual(result, 4)
4.2. 新建一个文件test02.py,用例如下:
import unittestdef sub_( a, b):return a - bclass TestB(unittest.TestCase):def test_sub_1(self):result = sub_(4, 2)self.assertEqual(result, 2)def test_sub_2(self):result = sub_(4, 1)self.assertNotEqual(result, 4)
4.3. 新建一个文件003.py,通过TestSuite
选择用例进行执行:
import unittest
import test01
import test02suite = unittest.TestSuite()
# 添加test01文件中的用例test_add_1
suite.addTest(test01.TestA("test_add_1"))
# 添加test02文件中的用例test_sub_1
suite.addTest(test02.TestB("test_sub_1"))
runner = unittest.TextTestRunner()
runner.run(suite)
5. TestLoader(测试加载器)
5.1. 定义与作用
-
TestLoader
用于自动发现和加载测试用例。它可以根据指定的规则搜索测试模块、测试类和测试方法,并将它们加载到测试套件中。TestLoader
使得开发者可以方便地组织和执行大量的测试用例,而无需手动添加每个测试用例到测试套件中。
5.2. 主要方法
例如:
import unittestloader = unittest.TestLoader()
suite = loader.loadTestsFromModule(__name__)
-
loadTestsFromModule(module)
:从一个 Python 模块中加载测试用例。loadTestsFromTestCase(test_case_class)
:从一个测试用例类中加载测试用例。loadTestsFromName(name)
:根据给定的名称加载测试用例,可以是模块名、类名或方法名。
5.3. 示例
5.3.1. loadTestsFromModule(module)
创建一个名为my_module.py
的模块,其中包含以下测试用例类:
# my_module.py
import unittestclass MyTestCase1(unittest.TestCase):def test_method1(self):self.assertEqual(2 + 2, 4)class MyTestCase2(unittest.TestCase):def test_method2(self):self.assertTrue(5 > 3)
使用loadTestsFromModule
执行用例
import unittest
import my_moduleloader = unittest.TestLoader()
suite = loader.loadTestsFromModule(my_module)runner = unittest.TextTestRunner()
runner.run(suite)
5.3.2. loadTestsFromTestCase(test_case_class)
创建一个测试用例类定义如下:
import unittestclass MySpecialTestCase(unittest.TestCase):def test_something(self):self.assertEqual(3 * 3, 9)def test_another_thing(self):self.assertFalse(2 == 3)
使用loadTestsFromTestCase执行用例
:
import unittest
from your_module import MySpecialTestCaseloader = unittest.TestLoader()
suite = loader.loadTestsFromTestCase(MySpecialTestCase)runner = unittest.TextTestRunner()
runner.run(suite)
5.3.3. loadTestsFromName(name)
- 以模块名为例:
-
- 创建一个模块
test_module.py
,其中包含测试用例类。
- 创建一个模块
# test_module.py
import unittestclass TestInModule(unittest.TestCase):def test_one(self):self.assertEqual(4 * 2, 8)
import unittestloader = unittest.TestLoader()
suite = loader.loadTestsFromName('test_module') # 注意这里有引号runner = unittest.TextTestRunner()
runner.run(suite)
- 以类名为例:
-
- 继续使用上面的
test_module.py
模块。
- 继续使用上面的
import unittestloader = unittest.TestLoader()
suite = loader.loadTestsFromName('test_module.TestInModule') # 注意这里有引号runner = unittest.TextTestRunner()
runner.run(suite)
- 以方法名为例:
-
- 同样使用上面的模块。
import unittestloader = unittest.TestLoader()
suite = loader.loadTestsFromName('test_module.TestInModule.test_one') # 注意这里有引号runner = unittest.TextTestRunner()
runner.run(suite)
6. Fixture
6.1. 定义与作用
-
- Fixture 是在测试用例执行前后执行的一组操作,用于设置测试环境和清理资源。例如,在测试数据库操作时,可以在测试用例执行前连接数据库,在测试用例执行后关闭数据库连接。
- Fixture 可以确保每个测试用例都在相同的初始状态下执行,提高测试的可重复性和可靠性。
6.2. 主要方法
例如:
import unittestclass MyTest(unittest.TestCase):@classmethoddef setUpClass(cls):print("Set up class.")def setUp(self):print("Set up.")def test_method(self):print("Running test method.")def tearDown(self):print("Tear down.")@classmethoddef tearDownClass(cls):print("Tear down class.")
-
setUp()
:在每个测试用例执行前调用,用于设置测试环境。tearDown()
:在每个测试用例执行后调用,用于清理测试环境。setUpClass()
:在测试类的所有测试用例执行前调用一次,通常用于执行一些耗时的初始化操作,如连接数据库。tearDownClass()
:在测试类的所有测试用例执行后调用一次,用于清理资源,如关闭数据库连接。
总之,unittest
的这些核心要素相互配合,提供了一个强大的测试框架,帮助开发者编写、组织和执行单元测试,以确保代码的质量和稳定性。
三、断言(Assertions)
1. 定义和作用
-
- 断言是用于验证测试结果是否符合预期的语句。在测试用例中,通过断言来检查实际结果与预期结果是否一致。如果断言失败,测试用例将被标记为失败。
- 断言可以帮助开发者快速发现代码中的错误,提高代码的质量和可靠性。
2. 常见的断言方法
例如:
import unittestclass MyTest(unittest.TestCase):def test_equal(self):self.assertEqual(2 + 2, 4)def test_not_equal(self):self.assertNotEqual(2 + 2, 5)def test_true(self):self.assertTrue(2 < 3)def test_false(self):self.assertFalse(2 > 3)
-
assertEqual(a, b)
:断言a
和b
相等。assertNotEqual(a, b)
:断言a
和b
不相等。assertTrue(x)
:断言x
为True
。assertFalse(x)
:断言x
为False
。assertIs(a, b)
:断言a
和b
是同一个对象。assertIsNot(a, b)
:断言a
和b
不是同一个对象。assertIsNone(x)
:断言x
是None
。assertIsNotNone(x)
:断言x
不是None
。assertIn(a, b)
:断言a
在b
中。assertNotIn(a, b)
:断言a
不在b
中。
四、参数化(Parameterization)
1. 定义和作用
-
- 参数化测试是一种将相同的测试逻辑应用于不同的输入数据的技术。通过参数化,可以减少重复的测试代码,提高测试的效率和覆盖度。
- 参数化测试可以使用不同的输入数据来验证代码的正确性,从而发现更多的错误。
2. 实现方法
2.1. 使用 unittest.TestCase.subTest()
方法
-
- 使用
unittest.TestCase.subTest()
方法:可以在一个测试方法中使用subTest
方法来对不同的输入数据进行测试。每次调用subTest
方法时,都会执行相同的测试逻辑,但使用不同的输入数据。
- 使用
import unittestclass MyTest(unittest.TestCase):def test_addition(self):data = [(2, 3, 5), (4, 5, 9), (6, 7, 13)]for a, b, expected in data:with self.subTest(a=a, b=b):self.assertEqual(a + b, expected)
2.2. 使用第三方库
-
- 如
pytest
或parameterized
:这些库提供了更强大的参数化测试功能,可以更方便地实现参数化测试。 - 安装第三方库: pip install parameterized
- 导包:from parameterized import parameterized
- 代码示例:
- 如
import unittest
from parameterized import parameterizeddef add_numbers(a, b):return a + bclass TestAddNumbers(unittest.TestCase):@parameterized.expand([(1, 2, 3),(4, 5, 9),(10, -5, 5)])def test_add_numbers(self, a, b, expected_result):result = add_numbers(a, b)self.assertEqual(result, expected_result)if __name__ == '__main__':unittest.main()
五、跳过(Skipping)
1. 定义和作用
-
- 有时候,某些测试用例可能在特定的条件下不适合执行,或者已知存在问题。在这种情况下,可以使用跳过机制来跳过这些测试用例,避免不必要的失败。
- 跳过测试用例可以提高测试的效率,并且可以在特定的情况下避免错误的报告。
2. 实现方法
例如:
import unittestclass MyTest(unittest.TestCase):@unittest.skip("This test is skipped for now.")def test_skipped_method(self):pass@unittest.skipIf(2 > 3, "This test is skipped if 2 > 3.")def test_skipped_if_method(self):pass@unittest.skipUnless(2 < 3, "This test is skipped unless 2 < 3.")def test_skipped_unless_method(self):pass
-
- 使用
unittest.skip(reason)
装饰器:可以在测试方法上使用skip
装饰器来跳过该测试用例。reason
参数是一个字符串,用于说明跳过的原因。 - 使用
unittest.skipIf(condition, reason)
装饰器:可以根据特定的条件来跳过测试用例。如果condition
为True
,则跳过该测试用例。 - 使用
unittest.skipUnless(condition, reason)
装饰器:与skipIf
相反,只有当condition
为True
时,才执行该测试用例。
- 使用
六、生成 HTML 测试报告
1. 定义和作用
-
- 生成 HTML 测试报告可以将测试结果以更直观的形式展示出来,方便开发者查看和分析测试结果。
- HTML 测试报告可以包含测试用例的名称、执行时间、结果状态等信息,以及详细的错误信息和堆栈跟踪。
2. 实现方法
例如,使用 HTMLTestRunner
(这里可能会出现兼容问题,生成报告内容为空,具体问题具体解决):
import unittest
import HTMLTestRunnerclass MyTest(unittest.TestCase):def test_method(self):self.assertEqual(2 + 2, 4)if __name__ == '__main__':suite = unittest.TestLoader().loadTestsFromTestCase(MyTest)with open('test_report.html', 'wb') as f:runner = HTMLTestRunner.HTMLTestRunner(stream=f, title='Test Report', description='Unit Test Results')runner.run(suite)
参数说明:
stream:open 函数打开的文件流;
title:[可选参数],为报告标题;
description:[可选参数],为报告描述信息;比如操作系统、浏览器等版本;
-
- 使用第三方库,如
HTMLTestRunner
:HTMLTestRunner
是一个用于生成 HTML 测试报告的第三方库。可以将测试用例的执行结果输出为 HTML 格式的报告。 - 使用
unittest
的TextTestRunner
并结合其他工具:可以使用TextTestRunner
来执行测试用例,并将结果输出到一个文件中。然后,可以使用其他工具将文本报告转换为 HTML 格式的报告。
- 使用第三方库,如
总之,unittest
模块提供了丰富的功能来支持单元测试,包括Fixture、断言、参数化、跳过和生成 HTML 测试报告等。这些功能可以帮助开发者提高代码的质量和可靠性,并且可以更方便地进行测试和调试。
相关文章:
软件测试基础十七(python Unittest)
Unittest 一、Unittest 简介 unittest是 Python 内置的标准测试框架,用于编写和运行单元测试。它提供了一组工具和类,帮助开发者组织、编写和执行测试用例,以验证代码的正确性。 二、Unittest 核心要素 1. TestCase(测试用例类…...

技术领导者的道与术:从领导者到领导力
目录标题 领导者现实看起来是这样技术领导者不应该和个人坐在一起技术领导力仍然是必须的从技术领导到技术领导力小结领导者 你可能想成为或者已经是一位技术领导者,估计你现在心里想成为超级英雄的想法正在爆棚。 你是Java、JavaScript、Angular等技术的专家,公司的项目代…...
Starrocks Compaction的分析
背景 本文基于 Starrocks 3.1.7 结论 Starrocks 会启动一个线程周期性的去进行Compaction,该周期间隔为 200 MS, 该Compaction以table的partition为切入点,tablet(也就是bucket)为粒度进行task的创建。 分析 CompactionMgr start 方法会启动一个Com…...
淘淘商城实战高并发分布式项目(有源码)
通过百度网盘分享的文件:淘淘商城实战高并发分布式项目(有源码) 链接:https://pan.baidu.com/s/1V94gRALxHgMVwpcXoE-miA?pwdglu7 提取码:glu7 在互联网技术飞速发展的当下,高并发分布式项目成为了众多电商平台等大型应用的核心…...

内网部署web项目,外网访问不了?只有局域网能访问!怎样解决?
相关技术 要实现“内网部署,外网访问”,可以使用内网穿透、VPN技术、DMZ主机、端口映射等方法。以下是对这些方法的详细解释: 一、内网穿透 内网穿透是一种技术,它通过将内网设备映射到公网上的方式,实现外网访问内…...
Jenkins系列
jenkins 1、搭建Jenkins 搭建Jenkins 2、这是什么 3、这是什么 4、 这是什么 5、这是什么 文章目录 jenkins1、搭建Jenkins2、这是什么3、这是什么4、 这是什么5、这是什么 前言 前言 提示:这里可以添加本文要记录的大概内容: 例如:随…...
技术总结(二十四)
一、Redis 分布式锁的常见使用场景有哪些? 资源竞争控制 数据库事务控制:在分布式系统中,多个服务可能会同时对数据库中的同一行数据进行操作。例如,在一个电商系统里,多个订单处理服务可能会同时尝试更新同一个订单的…...

原生鸿蒙应用市场:赋能开发者全生命周期服务体验
文章目录 背景自动化检测前移:早发现,早解决技术细节:静态代码分析与兼容性测试应用场景 按需加载:优化性能,提升用户体验技术细节:模块化与懒加载实现应用场景 应用加密:保护应用代码安全&…...
深入解析TOML、XML、YAML和JSON:优劣对比与场景应用
摘要:本文将介绍四种常见的配置文件和数据交换格式:TOML、XML、YAML和JSON,通过具体的使用例子分析它们的优缺点,并探讨在不同场景下的应用选择。 正文: 一、TOML 优点: 易于阅读和编写:TOML的…...
前端UniApp面试题及参考答案(100道题)
目录 UniApp 支持哪些平台? UniApp 在不同平台上的表现有何差异? 如何处理 UniApp 中的平台差异? UniApp 项目创建与目录结构 项目创建 目录结构 如何创建一个 UniApp 项目? UniApp 项目的基本目录结构是什么样的? 解释一下 UniApp 中的页面生命周期钩子函数有哪…...

MoonBit 双周报 Vol.59:新增编译器常量支持,改进未使用警告,支持跨包函数导入...多个关键技术持续优化中!
2024-11-04 MoonBit更新 增加了编译期常量的支持。常量的名字以大写字母开头,用语法 const C ... 声明。常量的类型必须是内建的数字类型或 String。常量可以当作普通的值使用,也可以用于模式匹配。常量的值目前只能是字面量: const MIN_…...

Linux相关概念和易错知识点(20)(dentry、分区、挂载)
目录 1.dentry (1)路径缓存的原因 (2)dentry的结构 ①多叉树结构 ②file和dentry之间的联系 ③路径概念存在的意义 2.分区 (1)为什么要确认分区 (2)挂载 ①进入分区 ②被挂…...

论 ONLYOFFICE:开源办公套件的深度探索
公主请阅 引言第一部分:ONLYOFFICE 的历史背景1.1 开源软件的崛起1.2 ONLYOFFICE 的发展历程 第二部分:ONLYOFFICE 的核心功能2.1 文档处理2.2 电子表格2.3 演示文稿 第三部分:技术架构与兼容性3.1 技术架构3.2 兼容性 第四部分:部…...

兵马未动,粮草先行-InnoDB统计数据是如何收集的
我们前面介绍查询成本的时候经常用到一些统计数据,比如通过SHOW TABLE STATUS可以看到关于表的统计数据,通过SHOW INDEX可以看到关于索引的统计数据,那么这些统计数据是怎么来的呢?它们是以什么方式收集的呢?本章将聚焦…...
oracle服务器意外宕机数据库启动失败故障处理记录
客户反馈由于服务器意外宕机,导致数据库业务不能正常运行,经过一番努力后通过redo日志恢复成功! 故障描述:ORA-00600: 内部错误代码, 参数: [krctcr_4], [1179922061], [1179942042], [], [], [], [], [], [], [], [], [] 现将主要…...

学习笔记——MathType公式编号:右编号和随章节变化
1.如何在word文档中插入带有编号的公式? 步骤:(前提是已经安装mathtype) 2.MathType公式编号怎么随章节变化? 想要编号级数也随标题级数进行自动变化,则需要插入或修改文档的“分隔符” 步骤:...

如何使用 SSH 连接并管理你的 WordPress 网站
在当今数字化的世界里,网站的管理与维护至关重要。对于使用 WordPress 搭建网站的用户而言,掌握基本的 SSH(安全壳)命令能够极大地简化网站管理工作。本指南将向你介绍 SSH 的基本知识,并教你如何通过 SSH 连接和管理你…...
力扣60. 排列序列
描述 力扣60. 排列序列 给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。 按大小顺序列出所有排列情况,并一一标记,当 n 3 时, 所有排列如下: “123” “132” “213” “231” “312” “321” 给定 n 和 k,返回…...

Mac如何实现最简单的随时监测实时运行状态的方法
Mac book有着不同于Windows的设计逻辑与交互设计,使得Mac book有着非常棒的使用体验,但是在Mac电脑的使用时间过长时,电脑也会出现响应速度变慢或应用程序崩溃的情况,当发生的时候却不知道什么原因导致的,想要查询电脑…...
时间管理应用(可复制源码)
创建一个简单的时间管理应用程序,结合 Pomodoro 技术使用 HTML、CSS 和 JavaScript 1. HTML 创建一个基本的 HTML 文件 (index.html): <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"&…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...