兔c同学的一篇:使用python 的 unittest模块对类和函数进行测试
创始人
2024-06-01 05:21:46
0

文章目录

        • 1. 测试函数
            • 简单的函数测试
            • 单元测试和测试用例
            • 可通过的测试
            • 不可通过的测试
            • 测试未通过时怎么办
        • 2. 测试类
            • 各种断言方法
            • 测试一个类
            • 测试 AnonymousSurvey
            • 方法setUp()

导言

在编写函数或类时,还可为其编写测试。通过测试,可以确定代码面对各种输入都能够按要求的那样工作。或者在程序添加新的代码功能时,你也可以对其进行测试,确认它们不会破坏程序既有的作为。程序员都会犯错,因此每个程序员都必须经常测试其代码,在用户发现问题前找出它们。
本章,我们将讲述如何使用 python 的 unittest 中的工具来测试代码,我们进行编写测试用例,核实一系列输入都将得到预期的输出。我们可以看到通过测试将会是什么样子,测试未通过又是什么样子,还将知道测试未通过如何有助于改进代码。你将学习如何测试函数和类,并将知道该为项目编写多少个测试。

1. 测试函数

简单的函数测试

进行函数测试的前提是有可以进行测试的代码。
我们先编写一个简单的函数,它接受名和姓并返回整洁的姓名:

def get_name(first,last):name = first +" "+lastreturn name.title()

现在我们开始编写测试代码,
我们可以用前面章节学到的知识进行结合,模拟一个用户输入信息的场景,
当用户输入完成自己的用户名信息后,给其返回他录入的信息,告诉他定义的信息为:


from name_test import get_nameprint('您已成功登陆系统,请录入您的用户名.....')while True:firstname = input('请录入您的姓氏:')lastname = input('请您继续存储您的名称:')names = get_name(firstname,lastname)print("您注册的用户名称为:"+ names)

经测试运行后发现,我们编写的返回姓名信息的函数逻辑是正确可行的。


单元测试和测试用例

python 标准库中的模块 unittest提供了代码测试工具。单元测试用于核实函数的某个方面没有问题;
测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。全覆盖式测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖可能很难。通常,最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖。


可通过的测试

创建测试用例的语法需要一段时间才能习惯,但测试用例创建后,再添加针对函数的单元测试就很简单了。

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

#导入单元测试
import unittest#导入进行测试的函数
from name_test import get_name#创建类,用于包含一系列针对测试函数的单元测试
class NamesTestCase(unittest.TestCase):#开始进行函数测试def test_first_last_name(self):name = get_name('兔','c')self.assertEqual(name,'兔 C')unittest.main()

编写的这段单元测试代码,测试的上一小节知识点中定义的 get_name()函数。
在这个代码中,导入了两个类,我们先看一下运行结果,在来解释代码行。

看看运行结果,到底能否通过调用 get_name()函数 返回名字。
在这里插入图片描述

第一行的句点表明有一个测试通过了。接下来的一行指出python运行了一个测试,消耗的时间不到0.001秒。最后一行的ok表示该测试用例中的单元测试都通过了。

接下来,我们开始逐行解释单元测试中的代码行。

首先,我们导入了模块 unittest,还有要进行测试的 get_name() 函数。
然后,我们又创建了一个类,类名为 NamesTestCase,用于包含一系列针对get_name的单元测试。至于类的命名规范一定要与进行测试的内容相关,并且还要包含Test字样。除了这些规范,还一定要继承 unittest.TestCase类,这样 python 才会知道如何运行你编写的测试。


NamesTestCase 只包含一个方法,用于测试 get_name() 函数的一个方法。我们将这个方法命名为 test_name_last_name()。因为我们要核实的是只有名和姓的姓名能否被正确的格式化。
当我们运行当前这个类的后缀为.py 文件时,所有 以 test 打头的方法都将自动运行。在这个方法中,我们调用了要测试的函数,并存储了要测试的返回值。在这个示例中,我们使用实参 ‘兔’ 和 'c’调用 get_name(),并将返回的结果存储到 name 变量当中。


unittest 类最有用的功能之一:一个断言方法。断言方法用来核实得到的结果是否与期望的结果一致。在这里,我们知道 get_name() 应返回这样的姓名,集名和姓的拼接,如果是英文,就以首字母大写的形式返回。
为了检查返回的内容和我们输入的内容是否一致,我们调用 unittest 的方法:assertEqual() ,至于这个方法中需要传递的参数,1 是变量,也就是存储了 获得到get_name 函数返回内容的变量。2 是 与其相对应的内容。也就是手动录入字符串内容,和其变量中存储的内容进行比对,当然这个比对是通过 asertEqual() 函数进行的。
最后,如果内容相等,就会返回如上图中的结果,反之,它会告诉我们错误信息。


不可通过的测试

什么样的测试不可通过呢?
例如上述示例中,我们定义的 get_name函数只能接收两个参数,但是并非所有人的名字都是两个字的,如果出现三个字的情况呢?

接下里,我们就测试一下三个字的名字,在调用 unittest.assertEqual() 函数进行校对:

import unittest
from name_test import get_nameclass NamesTestCase(unittest.TestCase):#单元测试类中的函数一定要以test开头,才会在测试类启动时自动运行def test_first_last_name(self):name = get_name('兔','c','c')self.assertEqual(name,'兔CC')unittest.main()

看一下运行结果:
在这里插入图片描述
python 解释器开始向我们说明错误了:

可以看到其中包含的信息很多,因为测试未通过。
第一行输出了一个字母E,它指出测试用例中有一个单元测试导致了错误。并且也给我们指出了错误所在行。
测试用例在包含众多单元测试时,知道哪个测试未通过至关重要,traceback,指出函数调用的有问题。
这里我们知道,自己定义的get_name 函数只能接收两个形参,而我们却传递了三个实参。


测试未通过时怎么办

如果你检查的条件没有错误,那说明测试通过了,也意味着函数的行为是对的。
而测试未通过就意味着我们编写的代码有问题了,因此,测试未通过时,不要修改测试,而应修复导致测试不能通过的代码:检查刚对函数所做的修改,找出导致函数行为不符合预期的修改。

现在,我们要做的就是去修改get_name() 函数了:

def get_name(first,last,middle =''):if middle:name = first + ' ' + middle + ' ' + lastelse:name = first + ' ' + lastreturn name.title()

改好了 get_name 函数,我们在执行一下刚才的单元测试:
在这里插入图片描述
可以看到,现在的测试结果就通过了。


2. 测试类

上半部分,我们编写了针对函数的测试用例。下面,我们将接触针对类的测试。在很多程序中都会用到类,因此能够证明你的类能够正确地工作会大有裨益。如果针对类的测试通过了,你就能确信对类所做的改进没有意外地破坏其原有的行为。

各种断言方法

python 在 unittest 模块中提供了很多断言方法。
我们前面探讨过,断言方法检查认为应该满足的条件是否确实满足。如果该条件满足,你对程序行为的假设得到了确认,你就可以确信其中没有错误。如果你认为应该满足的条件实际上并不满足,python 将引发异常。

下面我们来列举 六个常用的断言方法:

使用试着方法可以核实返回的值等于或不等于预期的值,返回的值为True 或 False,返回的值在列表中或不在列表中。你只能在继承 unittest.TestCase的类中使用这些方法。

方法用途
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中

测试一个类

类的测试与函数的测试相似——你所做的大部分工作都是测试类中方法的行为,但存在一些不同之处,下面来编写一个类进行测试。

一个帮助管理匿名调查的类:

class AnonymousSurvey():"""收集匿名调查问卷的答案"""#初始化方法:存储一个问题,并为存储答案做准备def __init__(self,question):self.question = question#空列表用于存储收集到的答案self.response = []#调查问题的方法	def show_question(self):print(self.question)#添加新答案的方法def store_response(self,new_response):self.response.append(new_response)#显示收集到的所有答案def show_results(self):for response in self.response:print('-调查结果: '+response)

我们用刚定义好的 AnonymousSurvey 类描述收集匿名调查问卷的答案。
其中:
__ init __ 初始化方法,用于收集一个问题,并将之后收集到的答案存储在空列表当中。
show_question 方法,用于调查问题。
store_response 方法,用于添加收集到的新答案。
show_results 方法,用于显示收集到的所有答案。


如果要想知道这个类能否正确地工作,我们需要编写一个使用它的类:

from survey import AnonymousSurvey#定义一个问题
question ="可以邀请您来参与我们的程序员问卷活动吗?"
#并使用这个定义的问题创建 AnonymousSurvey对象
my_survey = AnonymousSurvey(question)#显示问题
my_survey.show_question()
print('录入q键可终止调查活动.....')while True:response = input('请问您最喜欢哪一门编程语言?')if response == 'q':breakmy_survey.store_response(response)#显示调查结果:
print('感谢您对本次调查问卷活动的支持!')
my_survey.show_results()

现在,我们编写好了 用于进行匿名调查问卷的 AnonymousSurvey 类,还有对该类进行使用的类,我们看一下使用的效果:
在这里插入图片描述

如果现在要对 AnonymousSurvey 类进行修改,例如:允许每位用户输入多个答案时,就会导致可能不小心修改处理单个答案的方式。要确认在开发这个模块时没有被破坏既有行为,可以编写针对这个类的测试。

测试 AnonymousSurvey

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

import unittest
from survey import AnonymousSurveyclass TestAnonymousSurvey(unittest.TestCase):def test_store_single_language(self):question = '请问可以邀请你参与程序员调查问卷吗?'my_survey = AnonymousSurvey(question)my_survey.store_response('c') #进行单个答案的存储self.assertIn('c',my_survey.response)
unittest.main()

在这段代码中,我们先导入了 unittest模块和 AnonymousSurvey 类。
接着,我们开始定义测试类,并且让测试类继承 unittest模块下的 TestCase类,
然后开始在测试类中定义测试方法,注意:测试方法需要以test_开头,这样在执行这个文件时,类中的test方法都会被自动执行。
同样的,我们先进行提问的问题设置,设置好了之后,创建存储该问题的实例,接下来,我们在通过实例来调用它内部的存储方法,将参数存储进去。
之后,调用核实内容是否在其内部的函数进行校对。

我们来看一下测试结果:
在这里插入图片描述
这很好,证明我们的代码都没有什么问题。可是只能收集一个答案的调查用途不大。
下面我们来核实用户提供三个答案时,它们也将被妥善地存储,为此,我们需要在 TestAnonymousSurvey 中再添加一个方法:

def test_stroe_three_response(self):#设置调查问题question = '请问您最喜欢哪一门编程语言?'#创建实例,并存储问题my_survey = AnonymousSurvey(question)#存储答案responses =['c','java','python']#遍历列表,将列表元素存储到调查问卷答案列表中for response in responses:my_survey.store_response(response)#再次遍历列表,调用 校对是否包含内容的assertIn方法for response in responses:self.assertIn(response,my_survey.response)

这次,我将代码行的逐行含义写在了注释中。
我们来看一下这个测试函数的测试结果:
在这里插入图片描述

方法setUp()

在前面的测试实例中,我们在每个测试方法中都创建了一个 AnonymousSurvey 实例,并在每个方法中都创建了答案。unittest.TestCase类包含方法 setUp(),让我们只需创建这些对象一次,并能够在每个测试方法中使用它们。

如果你在 TestCase类中包含了 setUp() 方法,python 将先运行它,再运行各个以test_打头的方法。这样,在你编写的每个测试方法中都可使用在方法setUp()中创建的对象了。

现在我们就使用 setUp()来创建一个调查对象和一组答案,供方法test_store_single_response() 和 test_store_three_responses() 使用:

from survey import AnonymousSurveyclass TestAnonymousSurvey(unittest.TestCase):def setUp(self):"""创建一个对象和一组答案,供使用的测试方法使用"""question = '请问你最喜欢哪一门编程语言?'self.my_survey = AnonymousSurvey(question)self.response = ['c','java','python']def test_store_single_language(self):self.my_survey.store_response(self.response[0])self.assertIn(self.response[0],self.my_survey.response)def test_store_three_responses(self):for response in self.response:self.my_survey.store_response(response)for response in self.response:self.assertIn(response,self.my_survey.response)
unittest.main()

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

相关内容

热门资讯

公司迎春晚会的主持词 公司迎春晚会的主持词  主持词的写作需要将主题贯穿于所有节目之中。在当今不断发展的世界,主持人在活动...
少儿节目主持词 精选少儿节目主持词4篇  主持词已成为各种演出活动和集会中不可或缺的一部分。随着社会一步步向前发展,...
王家卫电影经典台词 王家卫电影经典台词(精选50句)  我们爱看王家卫的电影,不止爱他所创造的那个光影世界,更爱他电影中...
演唱会主持台词 演唱会主持台词  (甲)尊敬的各位领导,  (乙)各位来宾,  (甲)敬爱的老师,  (乙)亲爱的同...
《你的名字》经典台词 《你的名字》经典台词  你的名字,是谁的心事,还记得你的名字里面的经典台词吗?以下是小编为你精心整理...
教研活动主持词 教研活动主持词  主持人在台上表演的灵魂就表现在主持词中。在当下的中国社会,主持成为很多活动不可或缺...
艺术节主持词开场白 艺术节主持词开场白  什么是艺术节  艺术节是文艺工作者及艺术家、艺术爱好者之间学术交流与学习的重要...
老板在公司年会致辞 老板在公司年会致辞15篇  在平平淡淡的学习、工作、生活中,大家最不陌生的就是致辞了吧,致辞具有针对...
央视春晚主持词台词 央视春晚主持词台词  主持词是主持人在节目进行过程中用于串联节目的串联词。在各种集会、活动不断增多的...
教师节朗诵晚会串词 教师节朗诵晚会串词  主持词需要富有情感,充满热情,才能有效地吸引到观众。在当今不断发展的世界,越来...
趣味运动会主持稿 趣味运动会主持稿(通用7篇)  在充满活力,日益开放的今天,很多地方都会使用到主持稿,主持稿是主持人...
鼠年文艺晚会的主持词 鼠年文艺晚会的主持词  1、喜鹊枝头叫,猴年已来到。好运来报道,健康身边绕。跨羊威武耀,进财装元宝。...
订婚仪式主持词 订婚仪式主持词(通用16篇)  主持词的写作需要将主题贯穿于所有节目之中。在人们积极参与各种活动的今...
文化艺术节闭幕词 文化艺术节闭幕词(精选6篇)  在日新月异的现代社会中,我们都可能会用到闭幕词,闭幕词的作用是辅助讲...
幼儿园签约仪式主持词 幼儿园签约仪式主持词  主持词没有固定的格式,他的最大特点就是富有个性。现今社会在不断向前发展,主持...
电影后来的我们台词 电影后来的我们台词  电影《后来的我们》可以说是风波不断,那么后来的我们经典语录台词有哪些?下面是小...
音乐串词 音乐串词甲:金牛报春来! 又是瑞雪飘飞的季节了,我们打一小学这个大家庭每到这时候总会欢聚一堂。 共庆...
不差钱的经典台词 不差钱的经典台词  赵本山:苏格兰调情。  小沈阳:人家是纯爷们。  丫蛋:洪湖水浪打浪,长江后浪推...
《终结者2》的经典台词 《终结者2》的经典台词  1.I’ll be back。  我会回来的。  2.I need you...
婚宴新娘致辞 婚宴新娘致辞(合集15篇)  无论在学习、工作或是生活中,大家都对致辞很是熟悉吧,在各种重大的庆典、...