Python入门实例——测试代码
文章目录
- 测试函数
- 单元测试和测试用例
- 测试类
- 各种断言方法
- 编写待测试的类
- 测试类
- 方法 setUp()
- 总结
测试函数
Python 模块 unittest 主要用来做测试代码使用,这样能够在自己编写代码后使用 Python 脚本编写简单测试代码完成自动测试。例如下面这样的简单函数:
def get_formatted_name(first, last):'''Generate a neattly formatted full name.'''full_name = first + ' ' + lastreturn full_name.title()
函数 get_formatted_name() 将名和姓合并成姓名,在名和姓之间加上一个空格,并将它们的首字母都大写,再返回结果。
接下来,为了核实该函数能够像期望的那样正常工作,编写如下测试例程来实现测试该函数的功能:
from name_func 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':breakformat_name = get_formatted_name(first, last)print("\nNeatly formatted name: " + formatted_name + ".")
执行结果如下:
上面这种方式只是最简单的通过自己输入参数并将输出打印出来观察是否正确,但是这太繁琐了。所幸 Python 提供了一种自动测试函数输出的高效方式 —— unittest 模块方式。
单元测试和测试用例
还是用于测试上面的函数,创建测试用例进行单元测试,测试代码如下:
import unittest
from name_func import get_formatted_nameclass NamesTestCase(unittest.TestCase):'''测试 name_func.py '''def test_first_last_name(self):'''能够正确处理姓名'''formatted_name = get_formatted_name('janis', 'jopin')self.assertEqual(formatted_name, 'Janis Jopin')unittest.main()
测试代码中,首先导入了模块 unittest
和测试函数对象 get_formatted_name()
。创建一个名为 NamesTestCase
的类,用于包含一系列针对测试对象的单元测试(可以随意给这个类命名)。这个类必须继承 unittest.TestCase类
,这样 python 才知道如何运行编写好的测试。
运行最后一行的 unittest.main()
可以使得 Python 运行这个文件中的测试。运行结果如下:
执行结果中第一行的 .
(句点)表明有一个测试通过了;接下来的一行指出了 Python 运行了一个测试,消耗的时间不到 0.003 秒,最后的 OK 表明该测试用例中的所有单元测试都通过了。
在开发时不可避免会对原来写好的函数进行修改,但是在源代码修改后,针对之前版本的测试代码也需要相应的修改了。下面对原来的函数进行如下修改:
# 添加中间姓名
def get_formatted_name(first, middle, last):'''Generate a neattly formatted full name.'''full_name = first + ' ' + middle + ' ' + lastreturn full_name.title()
再次执行刚刚编写的测试用例代码,显示结果如下:
可以看到显示的信息很多。
第一行输出的字母 E 指出测试用例中有一个单元测试导致了错误,接下来输出表示 NamesTestCase
中的 test_first_last_name()
导致了错误。当测试用例包含众多单元测试时,知道是哪个测试未通过至关重要。输出显示后面会弹出一个标准的 traceback
,指出了函数测试错误的问题,这里是因为缺少了一个必不可少的位置实参。
针对这个问题,我们其实可以将原函数修改成两个版本的兼容版本,具体如下:
def get_formatted_name(first, last, middle = ''):'''Generate a neattly formatted full name.'''if middle:full_name = first + ' ' + middle + ' ' + lastelse:full_name = first + ' ' + last return full_name.title()
在这个版本中,函数既可以接收三个参数的调用也同时可以接收旧版本的两参数调用,并且我们可以在原来的测试代码中添加新的测试用例,修改如下:
import unittest
from name_func import get_formatted_nameclass NamesTestCase(unittest.TestCase):'''测试 name_func.py '''def test_first_last_name(self):'''测试两参数正确处理姓名函数'''formatted_name = get_formatted_name('janis', 'jopin')self.assertEqual(formatted_name, 'Janis Jopin')def test_first_middle_last_name(self):'''测试三参数正确处理姓名函数'''formatted_name = get_formatted_name('janis', 'jopin', 'middle')self.assertEqual(formatted_name, 'Janis Middle Jopin')unittest.main()
执行这个新的测试用例,结果如下:
从结果可以看出,测试用例通过了。
测试类
前面已经说明针对单个函数的测试如何编写,但是 Python 作为面向对象的语言,更多的则是以类存在,所以在 Python 测试中其实更多的也是针对类的测试。在编写开发新的类后,如何能够证明你开发的新类能够正常工作或者能够使得代码开发正常。
接下来就是针对类的测试。
各种断言方法
Python 在 unittest.TestCase类
中提供了很多断言方法。前面能够看出,断言方法能够检查应该满足的条件是否确实满足。如果该条件确实满足,那么对程序行为的假设就得到了确认,也就可以确信这中间没用错误。如果实际上条件并没有得到满足,Python 将引发异常。
下面是6个常用到的断言方法。使用这些方法可以核实返回的值等于或不等于预期的值、返回的值为 True 或 False 、 返回的值在列表中或不在列表中。并且只能在继承 unittest.TestCase
的类中使用这些方法。
方法 | 用途 |
---|---|
assertEqual(a, b) | 核实 a == b |
assertNotEqual(a, b) | 核实 a != b |
assertTrue(x) | 核实 x 为 True |
assertFalse(x) | 核实 y 为 False |
assertIn(item, list) | 核实 item 在 list 中 |
assertNotIn(item, list) | 核实 item 不在 list 中 |
编写待测试的类
下面编写一个类进行测试,具体代码如下:
class AnonymousSurvey():'''收集匿名调查问卷的答案'''def __init__(self, question):'''存储一个问题,并为存储答案做准备'''self.question = questionself.responses = []def show_question(self):'''显示调查问卷'''print(self.question)def shore_response(self, new_response):'''存储单份调查问卷'''self.responses.append(new_response)def show_results(self):'''显示收集到的所有答案'''print("Survey results:")for response in self.responses:print("- " + response)
在个类首先需要存储一个指定的调查问题,并创建一个空列表,用于存储答案。这个类包含打印调查问题的方法、在答案列表中添加新答案的方法以及将存储在列表中的答案都打印出来的方法。要创建这个类的实例,只需要提供一个问题即可,有了类对象实例后,就可以使用 show_question()
来显示其中的问题,使用 shore_response()
来存储答案,并使用 show_results()
来显示调查结果。
具体使用方式如以下代码所示:
from survey import AnonymousSurvey# 定义一个问题,并创建一个表示调查的 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()
执行结果如下:
测试类
接下来就针对这个类的行为各方面编写一个测试代码,通过 assertIn()
来核实结果,具体代码:
import unittest
from survey import AnonymousSurveyclass TestAnonmyousSurvey(unittest.TestCase):'''针对AnonymousSurvey类的测试'''def test_store_single_response(self):'''测试单个答案会被妥善存储'''question = "What language did you first learn to speak?"my_survey = AnonymousSurvey(question)my_survey.shore_response("English")my_survey.shore_response("Chinese")self.assertIn("English", my_survey.responses)unittest.main()
执行测试代码结果如下:
添加测试用例,修改如下:
import unittest
from survey import AnonymousSurveyclass TestAnonmyousSurvey(unittest.TestCase):'''针对AnonymousSurvey类的测试'''def test_store_single_response(self):'''测试单个答案会被妥善存储'''question = "What language did you first learn to speak?"my_survey = AnonymousSurvey(question)my_survey.shore_response("English")self.assertIn("English", my_survey.responses)def test_store_three_responses(self):'''测试三个答案会被妥善地存储'''question = "What language did you first learn to speak?"my_survey = AnonymousSurvey(question)responses = ['English', 'Chinese', 'Mandarin']for response in responses:my_survey.shore_response(response)for response in responses:self.assertIn(response, my_survey.responses)unittest.main()
执行结果如下:
方法 setUp()
前面测试类的多个测试用例的代码中,每个测试用例都创建了一个实例对象及相应的操作。其实在 unittest.TestCase()
类中包含方法 setUp()
,这样我们只需要执行这些操作一次就可以在后面测试方法中使用它们。修改上面的代码如下:
import unittest
from survey import AnonymousSurveyclass TestAnonmyousSurvey(unittest.TestCase):'''针对AnonymousSurvey类的测试'''def setUp(self):'''创建一个调查对象和一组答案,供测试用例使用'''question = "What language did you first learn to speak?"self.my_survey = AnonymousSurvey(question)self.responses = ['English', 'Chinese', 'Mandarin']def test_store_single_response(self):'''测试单个答案会被妥善存储'''self.my_survey.shore_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.shore_response(response)for response in self.responses:self.assertIn(response, self.my_survey.responses)unittest.main()
执行结果如下:
可以看出两项测试也都通过了,并且测试代码编写的更精简了。
总结
本篇文章中,使用模块 unittest
中的工具为函数和类编写测试,编写继承 unittest.TestCase类
以及编写测试方法,使用 assert 断言的方式来核实函数和类的行为是否符合预期以判断测试是否通过。并且使用方法 setUp()
根据类高效创建实例并设置属性,以便在类的所有测试方法中可以使用它们,从而精简测试类代码的编写。
Python入门实例——测试代码相关推荐
- 2.python爬虫实战:爬取近5年的中国大学排行榜信息【Python】(测试代码+api例程)
目录 API说明: 思路 注意事项 完整代码 总结 欢迎关注 『Python』 系列,持续更新中 欢迎关注 『Python』 系列,持续更新中 爬取近5年的中国大学排行榜信息,在python爬虫爬取2 ...
- 几个好玩有趣的Python入门实例
几个好玩有趣的Python入门实例 几个简单的Python实例,好玩有趣,基础语法. turtle库开始自己的绘画 写一个属于自己的文本进度条 蒙特卡洛方法计算π 分形几何,Koch雪花曲线 输入一组 ...
- 45个python入门案例_几个好玩有趣的Python入门实例
几个好玩有趣的Python入门实例 几个简单的Python实例,好玩有趣,基础语法. turtle库开始自己的绘画 写一个属于自己的文本进度条 蒙特卡洛方法计算π 分形几何,Koch雪花曲线 输入一组 ...
- Python timeit库测试代码片段运行时间
timeit库文档:https://docs.python.org/zh-cn/3/library/timeit.html timeit 是一个用来测量小代码片段执行时间的工具库,有命令行和函数调用两 ...
- 提高C++性能的编程技术笔记:跟踪实例+测试代码
当提高性能时,我们必须记住以下几点: (1). 内存不是无限大的.虚拟内存系统使得内存看起来是无限的,而事实上并非如此. (2). 内存访问开销不是均衡的.对缓存.主内存和磁盘的访问开销不在同一个数量 ...
- python入门小游戏代码20行,python入门小游戏代码
python入门可以做的小游戏 1.Python入门拼图小游戏简单介绍:将图像分为m×n个矩形块,并将图像右下角的矩形块替换为空白块后,将这些矩形块随机摆放成原图像的形状. 2.Python入门推箱子 ...
- Python入门300行代码
#注:在python中需要注意代码之间的缩进,通常以一个tab的距离表示隶属关系 #1.利用import语句进行导入模块,用逗号分隔可以导入多个包 import os import math,copy ...
- Python新手入门之测试代码
编写函数或类的时候,可以编写测试,来确定代码面对各种输入都能够按要求的那样工作. 1.1 测试函数 下面写一个简单的函数来作为测试的代码.该函数接收姓名并返回完整的姓名.示例如下: 在编写一个使用该函 ...
- Python入门实例记录
文章目录 实例一 温度转换 实例二 turtle简单绘制 实例三 天天向上的力量 实例四 文本进度条 实例五 身体质量指数BMI 实例六 圆周率pi的计算 实例七 七段数码管绘制 实例八 科赫雪花绘制 ...
最新文章
- python读excel字体颜色_无法使用python xlsxwri更改excel中的字体颜色
- MM模块在做GR的时候几个需要注意的地方
- php vimrc配置文件,vim技巧:我的 .vimrc 配置文件,详解每一个配置项的作用
- mongodb数据库导出备份
- C语言 函数指针和指针函数区别 - C语言零基础入门教程
- 【测试】测试用例8大法
- 二分答案——小车问题(洛谷 P1258)
- android真实项目教程(三)——首页初点缀_by_CJJ
- Java对象创建、分配、布局、访问小析(HotSpot虚拟机)(二)
- 怎么遍历list集合赋值_Java 集合入门知识
- 145. 大小写转换
- c3p0连接池配置及实现详解
- 2021年网络工程师考试大纲
- 【渝粤题库】陕西师范大学152112 网络信息检索与利用
- Java编写的“滑稽”表情屏保程序
- 苹果园助力爱奇艺各业务协同作战,视频平台的战争将走向何方?
- 【Hulu独家面试宝典】助你决胜校招技术面
- Vivado使用技巧(2):综合运行与OOC
- 在word里面插入对象显示不全怎么办
- Three.js - 鼠标拾取(射线追踪法)(十九)