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

自动化测试系列 之 Python单元测试框架unittest

一、概述

什么是单元测试

单元测试是一种软件测试方法,是测试最小的可测试单元,通常是一个函数或一个方法。

在软件开发过程中,单元测试作为一项重要的测试方法被广泛应用。

为什么需要单元测试

单元测试是软件开发中重要的一环,具有以下作用:

  1. 验证代码的正确性:单元测试可以自动化地验证代码的正确性,避免开发人员手动测试时漏掉某些情况或错误。通过单元测试,可以及时发现和定位代码中的错误,并保障代码质量和缺陷率。
  2. 更好地组织和维护代码:通过单元测试,代码将被分割为小的可测试单元,每一个单元都有对应的测试用例,更好地组织代码,增加代码的可读性和可维护性。
  3. 提高开发效率:单元测试的快速执行和反馈,可以有助于开发人员快速找到问题并迅速地解决它们。这样可以加快迭代速度,提高软件开发效率。
  4. 自信心:通过单元测试,开发人员可以自信地修改和重构现有的代码,因为单元测试可以保证代码质量和正确性,减少犯错的机会。
Python 中的单元测试框架

各种编程语言都有自己的单元测试框架,Python中主流的单元测试框架包括:

  1. unittest: Python自带的单元测试框架,是xUnit风格的测试框架。
  2. pytest: 一个第三方的Python单元测试框架,具有更好的扩展性和灵活性。pytest具有更好的预期错误展示和简化测试用例编写的特点。
  3. nose: 另一个第三方的Python单元测试框架,它具有可插拔的插件架构,可以轻松地扩展其功能。
  4. doctest: Python自带的另一个单元测试框架,可以在Python代码中使用文档字符串编写测试用例
  5. Testify: 一个相对较新的Python单元测试框架,专注于在类与海量测试用例下提供更快速的速度和更好的效率。

本文将着重介绍Python自带的带有测试皇家 unittest

二、unittest框架介绍

unittest框架的背景和产生

unittest 是一个Java单元测试框架 JUnit 的Python版本。unittest最初由Python的核心开发者Tim Peters在2001年开发,旨在提供一种规范的方式来编写单元测试,以改进传统的debugging因试错所造成的时延。

unittest框架的特点与优势

unittest框架有以下特点与优势:

  • 标准化的测试工具: unittest框架提供了标准化的测试工具和从标准TestCase集成的测试运行器,为新手和高级用户提供了一个可用的接口。
  • 支持自动化测试: 可以通过编写自动化测试用例,加快测试效率,缩短测试时间,减少人工测试工作。
  • 支持测试定制: unittest框架可以轻松集成第三方库,支持创建自定义的测试用例和测试套件。
  • 执行结果明确: unittest框架提供了详细的错误信息,让测试人员能够快速地定位和修复错误。

三、unittest框架基础

安装和配置unittest框架

unittest是Python的内置模块,所以你不需要额外安装。

unittest 简单示例

被测试的代码demo,包含了两个方法, addsub

#!/usr/bin/env python3
# -*- coding: utf-8 -*-def add(a, b):return a + bdef sub(a, b):return a - b

为这两个函数编写单元测试用例

import unittest
from calculate import add, subclass TestCalcuate(unittest.TestCase):def test_add(self):result = add(2, 3)self.assertEqual(result, 5) def test_sub(self):result = sub(5, 3)self.assertEqual(result, 2)if __name__ == '__main__':unittest.main()

在这个测试用例中,我们导入了addsub函数,并创建了一个名为 TestCalcuate 的测试类(所有的测试类都必须是unittest.TestCase 的子类)。在这个类中,我们定义了两个测试方法test_addtest_sub,分别用于测试加法和减法函数的行为。

在每个测试方法中,我们调用相应的函数,并使用self.assertEqual断言方法来验证计算结果是否等于预期值。

最后,我们使用unittest.main()来运行测试用例。

四、unittest框架常用的测试类和方法

Python的unittest框架中,提供了许多用于辅助构建单元测试的类和方法

常用的测试类
  1. unittest.TestCase:这是unittest框架中最重要的测试类,所有的测试用例都应该继承自它。它提供了一些常用的断言方法和测试辅助方法,用于编写和运行测试。
  2. unittest.TestSuite:这个类用于组织和管理一组测试用例。你可以将多个测试用例添加到一个测试套件中,并一次性运行它们。
  3. unittest.TestLoader:这个类用于加载测试用例。它提供了一些方法,可以从模块、类或者目录中自动发现和加载测试用例。
  4. unittest.TextTestRunner:这个类用于运行测试用例并生成测试结果的文本报告。它提供了一些方法,可以控制测试的输出格式和详细程度。
  5. unittest.TestResult:这个类用于存储测试结果。它提供了一些方法,可以获取测试的状态、错误信息和失败信息等。
常用的方法

在unittest框架中,常用的方法包括setUp()tearDown()setUpClass()tearDownClass()。这些方法用于在测试用例的执行过程中进行准备和清理工作。

  1. setUp()方法:在每个测试方法运行之前调用。它用于准备测试环境,例如初始化对象、打开文件等。每个测试方法都会在调用setUp()方法后执行。
  2. tearDown()方法:在每个测试方法运行之后调用。它用于清理测试环境,例如关闭文件、释放资源等。每个测试方法都会在调用tearDown()方法后执行。
  3. setUpClass()方法:在测试类中的所有测试方法运行之前调用。它用于进行一次性的测试环境准备工作,例如连接数据库、启动服务器等。setUpClass()方法需要使用@classmethod装饰器进行标记。
  4. tearDownClass()方法:在测试类中的所有测试方法运行之后调用。它用于进行一次性的测试环境清理工作,例如断开数据库连接、关闭服务器等。tearDownClass()方法需要使用@classmethod装饰器进行标记。

这些方法可以在测试类中重写,并根据需要进行自定义操作。

五、编写测试用例

当使用unittest框架编写测试用例时,通常需要进行以下步骤:

  1. 创建测试用例:
    • 创建一个继承自unittest.TestCase的测试类。
    • 在测试类中定义一个或多个测试方法。每个测试方法应该以test_开头,以便unittest能够自动识别并运行它们。
    • 在每个测试方法中,编写测试逻辑并使用断言方法来验证结果是否符合预期。
  2. 管理测试用例:
    • 使用unittest.TestLoader类来加载测试用例。你可以使用loadTestsFromModule()方法从模块中加载测试用例,或者使用loadTestsFromTestCase()方法从测试类中加载测试用例。
    • 创建一个unittest.TestSuite对象,并将加载的测试用例添加到测试套件中。你可以使用addTest()方法添加单个测试用例,或者使用addTests()方法添加多个测试用例。
  3. 运行测试用例:
    • 使用unittest.TextTestRunner类来运行测试用例并生成测试结果的文本报告。
    • 创建一个unittest.TextTestRunner对象。
    • 调用run()方法运行测试套件,并将结果输出到控制台或文件中。

结合前面的例子,进一步演示如何编写、管理和运行测试用例:

import unittestclass MyTestCase(unittest.TestCase):def test_add(self):result = 2 + 2self.assertEqual(result, 4)def test_sub(self):result = 5 - 3self.assertEqual(result, 2)if __name__ == '__main__':# 创建测试套件并添加测试用例suite = unittest.TestSuite()suite.addTest(MyTestCase('test_add'))suite.addTest(MyTestCase('test_sub'))# 创建测试运行器并运行测试套件runner = unittest.TextTestRunner()runner.run(suite)

在这个示例中,我们创建了一个名为MyTestCase的测试类,并在其中定义了两个测试方法test_addtest_sub。然后,我们创建了一个测试套件,并使用addTest()方法将测试用例添加到测试套件中。最后,我们创建了一个测试运行器,并使用run()方法运行测试套件。

运行这个示例,你将看到测试结果的输出。如果所有测试通过,你将看到一个成功的消息。如果有测试失败,你将看到失败的消息和详细的错误信息。

这是使用unittest编写、管理和运行测试用例的基本步骤。你可以根据需要编写更多的测试方法,并使用各种断言方法来验证你的代码的行为。

六、unittest常用的断言方法

以下是unittest常用的断言方法以markdown表格的方式呈现:

断言方法

描述

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中

assertIsInstance(a, b)

断言a是b的实例

assertNotIsInstance(a, b)

断言a不是b的实例

assertRaises(exception, callable, *args, **kwargs)

断言调用callable(*args, **kwargs)会引发指定的异常

assertWarns(warning, callable, *args, **kwargs)

断言调用callable(*args, **kwargs)会引发指定的警告

assertLogs(logger=None, level=None)

断言在指定的日志记录器上发生了指定级别的日志记录

assertAlmostEqual(a, b, places=None, msg=None, delta=None)

断言a和b近似相等

assertNotAlmostEqual(a, b, places=None, msg=None, delta=None)

断言a和b不近似相等

assertSequenceEqual(a, b, msg=None, seq_type=None)

断言a和b是相同的序列

assertListEqual(a, b, msg=None)

断言a和b是相同的列表

assertTupleEqual(a, b, msg=None)

断言a和b是相同的元组

assertSetEqual(a, b, msg=None)

断言a和b是相同的集合

assertDictEqual(a, b, msg=None)

断言a和b是相同的字典

这些断言方法可以根据需要选择合适的方法来编写测试用例,并验证代码的行为是否符合预期。

相关文章:

自动化测试系列 之 Python单元测试框架unittest

一、概述 什么是单元测试 单元测试是一种软件测试方法,是测试最小的可测试单元,通常是一个函数或一个方法。 在软件开发过程中,单元测试作为一项重要的测试方法被广泛应用。 为什么需要单元测试 单元测试是软件开发中重要的一环&#xf…...

C语言朴素算法

#include <stdio.h> #include <string.h>// 朴素算法&#xff0c;用于字符串匹配 void naiveMatch(char* text, char* pattern) {int textLength strlen(text); // 计算文本串长度int patternLength strlen(pattern); // 计算模式串长度for …...

【力扣题解】P501-二叉搜索树中的众数-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P501-二叉搜索树中的众数-Java题解&#x1f30f;题目描述&#x1f4a1;题解&#x1f…...

Wnmp本地部署结合内网穿透实现任意浏览器远程访问本地服务

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 文章目录 前言1.Wnmp下载安装2.Wnmp设置3.安装cpolar内网穿透3.1…...

深信服AF防火墙配置SSL VPN

防火墙版本&#xff1a;8.0.85 需提前确认防火墙是是否有SSL VPN的授权&#xff0c;确认授权用户数量 1、确认内外网接口划分 2、网络→SSL VPN&#xff0c;选择内外网接口地址 3、SSL VPN→用户管理→新增一个SSL VPN的用户 4、新增L3VPN资源&#xff0c;类型选择Other&…...

在Spring Cloud中使用Gateway 网关

我们在上述文章中介绍了相关Spring Cloud的五大核心组件&#xff0c;现在我们来了解一下关于Spring Cloud的网关&#xff0c;关于使用网关&#xff0c;我们同时也需要知道他在一个架构中起到的作用&#xff0c;并且&#xff0c;我们需要知道网关具体的相关功能&#xff0c;本篇…...

【Python】配置环境变量

Python配置Windows系统环境变量 打开电脑属性 ——> 高级系统设置 ——> 高级 ——> 环境变量 Python安装目录 D:\Program Files\Python39 winR打开运行&#xff0c;输入cmd打开命令窗口 python -V...

使用.Net nanoFramework 驱动ESP32的OLED显示屏

本文介绍如何使用.Net nanoFramework 驱动ESP32的OLED显示屏。我们将会从最基础的部分开始&#xff0c;逐步深入&#xff0c;让你能够理解并实现整个过程。无论你是初学者还是有一定经验的开发者&#xff0c;这篇文章都会对你有所帮助。 1. 硬件准备 1.1 ESP32开发板 这里我们…...

0基础学习VR全景平台篇第134篇:720VR全景,云台调整节点

相机、云台和脚架全套设备组装完成后需要进行调校才能开始拍摄。这一节&#xff0c;我们将主要介绍云台调整的两个内容&#xff1a;对中心靶、调三点一线。&#xff08;后附调校原理&#xff09; 云台部件名称 一、调节准备 &#xff08;一&#xff09;对于安装好的云台 1.检…...

扫地机器人地图与用户终端的同步

以下内容为本人的学习笔记&#xff0c;如需要转载&#xff0c;请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/APaJheSbgTW3jNssWsp5Ng 地图数据来源于机器人算法模块&#xff0c;一般通过SLAM算法完成建图的过程。 建图过程中&#xff0c;基础数据涉及到各…...

使用机器学习进行语法错误检测/纠正

@francescofranco_39234 一、说明 一般的学习,特别是深度学习,促进了自然语言处理。各种模型使人们能够执行机器翻译、文本摘要和情感分析——仅举几个用例。今天,我们将研究另一个流行的用途:我们将使用Gramformer构建一个用于机器学习语法错误检测和纠正的管道。 阅读本文…...

从0到1快速入门ETLCloud

一、ETLCloud的介绍 ETL是将业务系统的数据经过抽取&#xff08;Extract&#xff09;、清洗转换&#xff08;Transform&#xff09;之后加载&#xff08;Load&#xff09;到数据仓库的过程&#xff0c;目的是将企业中的分散、凌乱、标准不统一的数据整合到一起&#xff0c;为企…...

QT上位机开发(会员管理软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们学习了ini文件的解析办法&#xff0c;通过QSettings类就可以很轻松地访问ini文件里面的数据。除了ini文件之外&#xff0c;另外一种经常出…...

线性代数笔记3 1.1

学习视频&#xff1a; 2.2 矩阵运算&#xff08;二&#xff09;_哔哩哔哩_bilibili 包括内容&#xff1a; p10矩阵运算&#xff08;二&#xff09; p11特殊矩阵 p12逆矩阵&#xff08;一&#xff09; p13逆矩阵&#xff08;二&#xff09;...

2023年12月编程语言排行榜

TIOBE Index for December 2023 December Headline: C# on its way to become programming language of the year 2023 2023年12月的TIOBE指数&#xff1a;12月头条:c#将成为2023年最佳编程语言 Yes, I know, we have been here before. At the end of 2022, it looked like …...

Redis VS Memcached:选择哪个更适合您的应用?

目录 1、前言 2、概念简介 2.1 Redis 2.2 Memcached 3、数据模型 4、持久性 5、分布式能力 6、性能和扩展性 7、如何选择适合您引用的缓存系统 8、结语 1、前言 Redis和Memcached都是常见的内存缓存系统&#xff0c;用于提升应用程序的性能和可扩展性。它们都具有高…...

【HarmonyOS开发】共享包HAR和HSP的创建和使用以及三方库的发布

OpenHarmony提供了两种共享包&#xff0c;HAR&#xff08;Harmony Archive&#xff09;静态共享包&#xff0c;和HSP&#xff08;Harmony Shared Package&#xff09;动态共享包。 HAR与HSP都是为了实现代码和资源的共享&#xff0c;都可以包含代码、C库、资源和配置文件&…...

安装 Node.js、npm

安装 nodejs 安装Node.js的最简单的方法是通过软件包管理器。 Node.js官网&#xff1a;https://nodejs.org/en/download/ cd /usr/local/src/wget -c https://nodejs.org/dist/v18.16.0/node-v18.16.0-linux-x64.tar.xz xz -d node-v18.16.0-linux-x64.tar.xz tar -xf node…...

解决报错:找不到显卡

今天做实验碰到一个问题&#xff1a;torch找不到显卡&#xff1a; 打开任务管理器&#xff0c;独显直接没了&#xff0c;一度以为是要去修电脑了&#xff0c;突然想到上次做实验爆显存&#xff0c;屏蔽了gpu用cpu训练&#xff1a; import os os.environ["CUDA_DEVICE_OR…...

如何使用Node.js快速创建本地HTTP服务器并实现公网访问服务端

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...