Python 基础:使用 unittest 模块进行代码测试

目录

  • 一、测试函数
    • 2.1 通过案例
    • 2.2 不通过案例
    • 2.3 添加新测试
  • 二、测试类
    • 2.1 单个测试案例
    • 2.2 多个测试案例
  • 三、总结

遇到看不明白的地方,欢迎在评论中留言呐,一起讨论,一起进步!
在这里插入图片描述
本文参考:《Python编程:从入门到实践(第2版)》

一、测试函数

首先我们准备一个要测试的函数,这个函数在名和姓之间加上一个空格并将其首字母大写,再返回结果。

"""文件名:name_function"""
def get_formatted_name(first,last):"""生成整洁的姓名。"""full_name = f"{first} {last}"return full_name.title()

我们再来编写一个使用该函数的程序:

from name_function import get_formatted_nameprint("Enter 'q' at any time to quit.")
while True:first = input("\nPlease give me a first name:")if first == 'q':breaklast = input("Please give me a last name:")if last == 'q':breakformatted_name = get_formatted_name(first,last)print(f"\tNeatly formatted name:{formatted_name}.")

运行结果如下:
在这里插入图片描述

Python 标准库中的模块 unittest 提供了代码测试工具。 单元测试用于核实函数的某个方面没有问题。这样一来我们就不用自己编写程序依次运行了。

测试用例是一组单元测试,它们用来核实函数在各种情形下的行为是否都符合要求。

要进行单元测试,可先导入模块 unittest要测试的函数,再创建一个继承 unittest.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试。

2.1 通过案例

下面的测试用例只包含一个方法,它检查函数 get_formatted_name() 在给定名和姓时能否正确工作:

import unittest
from name_function import get_formatted_nameclass NamesTestCase(unittest.TestCase):"""测试name_function.py。"""def test_first_last_name(self):"""能够正确地处理像Janis Joplin这样的姓名吗?"""formatted_name = get_formatted_name('janis','joplin')self.assertEqual(formatted_name,'Janis Joplin')if __name__ == '__main__':unittest.main()

在运行这段程序时,所有以 test_ 打头的方法都将自动运行,这里 test_first_last_name 将自动执行。

在函数 test_first_last_name 中,使用了 unittest 类最有用的功能之一:断言方法,用来核实得到的结果是否与期望的结果一致。

这里我们将介绍 6 种常用地断言方法。
注:只能在继承 unittest.TestCas 的类中使用这些方法

方法用途
assertEqual(a,b)核实 a == b
assertNotEqual(a,b)核实 a != b
assertTrue(x)核实 x == True
assertFalse(x)核实 x == False
assertIn(item,list)核实 item 在 list 中
assertNotIn(item,list)核实 item 不在 list 中

if 代码块检查特殊变量 __name__,这个变量是在程序执行时设置的。
如果这个文件作为主程序执行,变量 __name__ 将被设置为__main__,此时调用 unittest.main() 来运行测试用例。
如果这个文件被测试框架导入,变量 __name__ 的值将不是__main__,则不会调用 unittest.main()

运行这段程序结果如下:
在这里插入图片描述
最后的 OK 表明该测试用例中的所有单元测试都通过了。

2.2 不通过案例

下面我们对被测试的函数进行修改,用于处理有中间名的格式:

def get_formatted_name(first,middle,last):"""生成整洁的姓名。"""full_name = f"{first} {middle} {last}"return full_name.title()

我们仍然使用原来的测试用例,让它检查函数 get_formatted_name() 在给定名和姓时能否正确工作,最后运行结果如下:
在这里插入图片描述
这里我们可以清楚地看到发生了几处错误,错误具体在哪里发生。


要将中间名设置为可选的,可在函数定义中将形参 middle 移到形参列表末尾,并将其默认值指定为一个空字符串。还需要添加一个 if 测试,以便根据是否提供了中间名相应地创建姓名:

def get_formatted_name(first,last,middle=''):"""生成整洁的姓名。"""if middle:full_name = f"{first} {middle} {last}"else:full_name = f"{first} {last}"return full_name.title()

我们再来运行测试用例,最后运行结果如下:
在这里插入图片描述
现在,测试用例通过了。这意味着这个函数又能正确处理像 Janis Joplin 这样的姓名了,而且我们无须手工测试这个函数。 这个函数之所以很容易修复,是因为未通过的测试让我们得知新代码破坏了函数原来的行为。

2.3 添加新测试

下面我们再编写一个测试,用于测试包含中间名的姓名。为此,在 NamesTestCase 类中再添加一个方法:

import unittest
from name_function import get_formatted_nameclass NamesTestCase(unittest.TestCase):"""测试name_function.py。"""def test_first_last_name(self):"""能够正确地处理像Janis Joplin这样的姓名吗?"""formatted_name = get_formatted_name('janis','joplin')self.assertEqual(formatted_name,'Janis Joplin')def test_first_last_middle_name(self):  # 这里我们先添加了一个测试"""能够正确地处理像Wolfgang Amadeus Mozart这样的姓名吗?"""formatted_name = get_formatted_name('wolfgang', 'mozart', 'amadeus')self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')if __name__ == '__main__':unittest.main()

注意:测试方法名必须以 test_ 打头,这样它才会在我们运行时自动运行。

再次运行一下,两个测试都通过了!
在这里插入图片描述
现在我们知道,这个函数又能正确地处理像 Janis Joplin 这样的姓名了,而且深信它也能够正确地处理像 Wolfgang Amadeus Mozart 这样的姓名。

二、测试类

类的测试与函数的测试相似,我们所做的大部分工作是测试类中方法的行为。不过还是存在一些不同之处,下面编写一个要测试的类:

class AnonymousSurvey:"""收集匿名调查问卷的答案。"""def __init__(self,question):"""存储一个问题,并为存储答案做准备。"""self.question = questionself.responses = []def show_question(self):"""显示调查问卷。"""print(self.question)def store_response(self,new_response):"""存储单份调查答卷。"""self.responses.append(new_response)def show_results(self):"""显示收集到的所有答卷。"""print("Survey results:")for response in self.responses:print(f"- {response}")

为证明 AnonymousSurvey 类能够正确工作,编写一个使用它的程序:

from survey import AnonymousSurvey# 定义一个问题,并创建一个调查。
question = "What language did you first learn to speak?"
my_survey = AnonymousSurvey(question)# 显示问题并存储答案。
my_survey.show_question()
print("Enter 'q'at any time to quit.\n")
while True:response = input("Language:")if response == 'q':breakmy_survey.store_response(response)# 显示调查结果。
print("\nThank you to everyone who participated in the survey!")
my_survey.show_results()

执行结果如下:
在这里插入图片描述

2.1 单个测试案例

下面来编写一个测试,对 AnonymousSurvey 类的行为的一个方面进行验证:如果用户面对调查问题只提供一个答案,这个答案也能被妥善地存储。为此,我们将在这个答案被存储后,使用方法 assertIn() 来核实它确实在答案列表中:

import unittest
from survey import AnonymousSurveyclass TestAnonymousSurvey(unittest.TestCase):"""针对AnonymousSurvey类的测试。"""def test_store_single_response(self):"""测试单个答案会被妥善地存储。"""question = "What language did you first learn to speak?"my_survey = AnonymousSurvey(question)  # 创建实例my_survey.store_response('English')self.assertIn('English',my_survey.responses)if __name__ == '__main__':unittest.main()

注意:要测试类的行为,需要创建其实例。

运行上述代码,我们看到测试通过了:
在这里插入图片描述

2.2 多个测试案例

我们可以像测试函数一样定义多个以 “test_” 开头地函数来测试类的不同方面,这时我们需要在每个函数下都要对被测试的类进行实例化。

unittest.TestCase 类包含的方法 setUp() 让我们只需创建这些对象一次,就能在每个测试方法中使用:如果在 TestCase 类中包含了方法 setUp(),Python 将先运行它,再运行各个以 “test_” 打头的方法。这样,在我们编写的每个测试方法中,都可使用在方法 setUp() 中创建的对象。

下面使用 setUp() 来创建一个调查对象和一组答案,供方法 test_store_single_response()test_store_three_responses()使用:

import unittest
from survey import AnonymousSurveyclass TestAnonymousSurvey(unittest.TestCase):"""针对AnonymousSurvey类的测试。"""def setUp(self):"""创建一个调查对象和一组答案,供使用的测试方法使用。"""question = "What language did you first learn to speak?"self.my_survey = AnonymousSurvey(question)self.responses = ['English','Spanish','Mandarin']def test_store_single_response(self):"""测试单个答案会被妥善地存储。"""self.my_survey.store_response(self.responses[0])self.assertIn(self.responses[0],self.my_survey.responses)def test_store_three_responses(self):"""测试三个答案会被妥善地存储。"""for response in self.responses:self.my_survey.store_response(response)for response in self.responses:self.assertIn(response,self.my_survey.responses)if __name__ == '__main__':unittest.main()

运行结果如下:
在这里插入图片描述
测试自己编写的类时,方法 setUp() 让测试方法编写起来更容易:可在 setUp() 方法中创建一系列实例并设置其属性,再在测试方法中直接使用这些实例。相比于在每个测试方法中都创建实例并设置其属性,这要容易得多。

三、总结

在本文中,我们学习了:如何使用模块 unittest 中的工具来为函数和类编写测试,如何编写继承 unittest.TestCase 的类,以及如何编写测试方法,以核实函数和类的行为符合预期;如何使用方法 setUp() 来根据类高效地创建实例并设置其属性,以便在类的所有测试方法中使用。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/362421.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外贸SEO工具有哪些推荐?

"我们作为一个专业的Google SEO团队,比较推荐一下几个适合外贸SEO的工具。Ahrefs 是一个非常强大的工具,可以帮助你深入分析竞争对手的表现,找到有潜力的关键词,还可以监控你的网站链接状况。另外,SEMrush 也很不…

conda下安装32位版本python

前言:当前主流的系统为64bit系统,conda软件为64bit软件,因此使用conda创建虚拟环境安装python时默认安装的python为64bit版本,但部分研发场景需要调用32bit依赖,只能使用32bit的python,因此需要安装32bit的…

python OpenCV 库中的 cv2.Canny() 函数来对图像进行边缘检测,并显示检测到的边缘特征

import cv2# 加载图像 image cv2.imread(4.png)# 使用 Canny 边缘检测算法提取边缘特征 edges cv2.Canny(image, 100, 200)# 显示边缘特征 cv2.imshow(Edges, edges) cv2.waitKey(0) cv2.destroyAllWindows() 代码解析: 导入 OpenCV 库: import cv2加…

基于Java医院药品交易系统详细设计和实现(源码+LW+调试文档+讲解等)

💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,…

JavaScript中的Date对象,以及常用格式化日期的方法封装

一、Date对象 二、操作Date对象 1、创建Date对象 (1)常用方法 (2)使用示例 2、获取日期 (1)常用方法 (2)使用示例 3、设置日期 (1)常用方法 &…

【LeetCode】六、哈希集合Set相关:存在重复元素判断 + MyHashSet设计

文章目录 1、Set集合2、Java中的Set集合3、leetcode217:存在重复元素4、P705:设计哈希集合 1、Set集合 无序:写进去的顺序和遍历读出来的顺序不一样不重复 主要作用:查看是否有重复元素(给一个数组,转为…

信息技术课如何禁止学生玩游戏

在信息技术课上禁止学生玩游戏是一个常见的挑战,但可以通过一系列策略和工具来有效地实现。以下是一些建议: 明确课堂规则和纪律: (1)在课程开始时,明确告知学生课堂规则和纪律,包括禁止玩游戏的规定。 (2)强调遵守…

C#——this关键字详情

this关键字 在 C# 中,可以使用 this 关键字来表示当前对象,日常开发中我们可以使用 this 关键字来访问类中的成员属性以及函数。 使用this表示当前类的对象 执行结果 使用 this 关键字串联构造函数 执行结果 使用 this 关键字作为类的索引器 执行结果 …

diffusion model(十八):diffusion model中negative prompt的工作机制

info个人博客主页http://myhz0606.com/article/ncsn 前置阅读: DDPM: http://myhz0606.com/article/ddpm classifier-guided:http://myhz0606.com/article/guided classifier-free guided:http://myhz0606.com/article/classi…

用Roofline模型去分析pytorch和Triton算子

用Roofline模型去分析pytorch和Triton算子 1.参考链接2.测试环境3.安装相关依赖4.锁频5.获取理论算力6.创建测试脚本7.运行测试程序生成Roofline图8.NVIDIA Nsight Compute生成Roofline9.效果图A.nn.LinearB.Triton实现 本文演示了如何用Roofline模型去分析pytorch和Triton算子…

Vue2 - 项目上线后生产环境中去除console.log的输出以及断点的解决方案

前言 当你准备将Vue.js应用程序部署到生产环境时,一个关键的优化步骤是移除代码中的所有 console.log 语句以及断点。在开发阶段,console.log 是一个非常有用的调试工具,但在生产环境中保留它们可能会影响性能和安全性。在本文中,我将向你展示如何通过使用Vue CLI 2来自动…

【LLVM】学习使用PGO优化

笔者在查看PGO优化时看到了本站的这篇文章,其中代码和命令行部分贴上了序号,且命令行带上了$符号,不便于读者调试。 遂将代码重新整理到gitee,链接在此。 汇编代码分析 目前笔者使用的llvm版本为llvm-19,主要改动发生…

Postgresql从小白到高手 九 : psql高级查询及内部视图使用

Postgresql从小白到高手 九:pgsql 复杂查询及内部表高级查询 文章目录 Postgresql从小白到高手 九:pgsql 复杂查询及内部表高级查询一、多表查询二、pgsql内部表1.内部表2.内部表查询应用 一、多表查询 内联 :inner join on 简写 join on 结果集只有符合 筛选条件…

【Golang】Steam 创意工坊 Mod 文件夹批量重命名

本文将介绍一个使用Go语言编写的脚本,其主要功能是解析XML文件并基于解析结果重命名文件夹。这个脚本适用于需要对文件夹进行批量重命名,并且重命名规则依赖于XML文件内容的情况。 脚本功能概述 Steam创意工坊下载的Mod文件夹批量重命名为id名称 运行前…

maven仓库的作用以及安装 , DEA配置本地Maven

ay12-maven 主要内容 Maven的作用Maven仓库的作用Maven的坐标概念Maven的安装IDEA配置本地Maven 一、maven概述 1.1、项目开发中的问题 1、我的项目依赖一些jar包,我把他们放在哪里?直接拷贝到项目的lib文件夹中?如果我开发的第二个项目还是需要上面…

Linux系统编程(七)进程间通信IPC

进程间通讯的7种方式_进程间通信的几种方法-CSDN博客 管道 pipe(命名管道和匿名管道);信号 signal;共享内存;消息队列;信号量 semaphore;套接字 socket; 1. 管道 内核提供&#x…

亿发进销存管理系统+:多终端无缝协同,实现经营销售场景全覆盖

亿发软件凭借产品、市场、业务的深入理解,在进销存基础上进行了延伸,推出多终端、一体化的“进销存管理系统”多元产品矩阵。对企业经营中进货、出货、销售、付款等进行全程跟踪管理。有效辅助企业解决业务管理、销售管理、库存管理、财务管理等一系列问…

如何做到高级Kotlin强化实战?(一)

高级Kotlin强化实战(一) 第一章 Kotlin 入门教程1.Kotlin 入门介绍2.Kotlin 与 Java 比较 第一章 Kotlin 入门教程 1.Kotlin 入门介绍 Kotlin 概述 Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言。它主要是 JetBrains 开发团队所开发出来的编程…

卸载vmware时2503,2502报错的解决办法

1.背景 windows 卸载vmware时,显示2503报错,无法完全卸载 2. 解决方案 2.1 参考安装报错2502,2503的处理方式 文献:https://blog.csdn.net/zhangvalue/article/details/80309828 2.1 步骤: 2.1.1 cmd 管理员打开…

实时美颜技术解析:视频美颜SDK如何改变直播行业

实时美颜技术的出现,尤其是视频美颜SDK的应用,正逐渐改变着直播行业的生态。 一、实时美颜技术的原理 实时美颜技术利用人工智能和图像处理算法,对视频中的人物面部进行优化和修饰。该技术通常包含以下几个步骤: 1.人脸检测和识…