使用unittest进行函数和类的单元测试

本文介绍了如何使用Python的unittest模块进行函数和类的单元测试,包括创建测试用例、常用断言方法如assertEqual、assertTrue等,以及针对函数和类的不同测试场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用unittest进行函数和类的单元测试入门级

unittest是python模块中的一个单元测试框架,它里面包含了TestCase基类,TestCase基类可以用来新建测试用例,这个类中提供了众多的断言方法,可以使用断言来检查你编写的测试case中的一些假设条件是否成立。
Python在unittest.TestCase类中供了很多断言方法。使用断言方法可以来检查你的case中假设应该满足的条件是否确实满足。如果该条件确实满足,你对程序行为的假设就得到了确认,可以确信其中没有错误。如果你认为应该满足的条件实际上并不满足,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不存在

一、怎样针对一个函数来创建一个测试用例

举个例子:
现在有一个函数,他的形参是用来分别接受名字中的姓和名,最后返回整个姓名

def get_formatted_name(first, last, middle = ''):
        full_name = f"{first} {last}"
        """title方法用来返回一个字符串的首字母大写后的格式"""
        return full_name.title() 

我们现在要针对这个函数来创建一个测试方法,这个函数是否能正确拼接姓和名并返回最后正确的姓名。要为get_formatted_name函数编写测试用例,我们要先导入模块unittest,再创建一个继承unittest.TestCase 的类,然后在这个继承了TestCase基类中的测试类中编写一系列方法对函数行为的不同场景进行测试

#首先在创建测试类之前导入unittest模块
import unittest
#创建继承unittest中的TestCase测试类
class NameTestCase(unittest.TestCase):
    
    """之后再类中针对要测试函数创建对应的测试case,这样当程序跑起来的时候,python就知道怎样去执行你编写的测试case"""
    """这里创建测试case的时候的函数命名要以test开头这样就告诉了python要怎样运行这个测试方法"""
    def test_first_name_case(self):
        #这里我们只需要测试这个函数能否正确返回正确格式的姓名拼接 所以我们将姓和名分别传给他看他是否能正确返回,然后将返回值和期望值进行断言比较,如果相等就证明测试通过,如果不相等就证明测试不通过
        name =  get_formatted_name('janis', 'joplin')
        #assertEqual是用来判断传的两个参数是否相等的断言 
         self.assertEqual(formatted_name, 'Janis Joplin') 
 
 if __name__ == '__main__':
        unittest.main() # 在这里,调用unittest.main()来运行测试用例。 

之后运行程序,得到下面的输出, 第一行的句点表明有一个测试通过了。接下来的一行指出Python运行了一个测试case,消耗的时间不到0.000秒。最后的OK表明该测试用例中的所有单元测试都通过了

那如果此时这个函数内部的逻辑进行了改动,这时他需要接受三个参数,姓名中多了一个中间名,那我们上面编写的测试用例就会测试不通过
变动后的函数:

 def get_formatted_name(first, middle, last): 
     full_name = f"{first} {middle} {last}" 
     return full_name.title()

此时我们再去运行上面编写的测试case就会显示不通过

这个报错信息中非常明确的指出来,get_formatted_name()这个函数需要三个参数,但是我们调用时只传了两个参数。如果在实际的测试中执执行测试用例之后发现报错,第一时间我们先要去检查我们编写的case实际场景下是否存在,并且编写的case没有错误,此时再去检查测试的函数。不要根据函数的变动来随时更改我们的测试case,有时候函数的变动所包含的逻辑可能并不在设计的场景中。

二、如何针对一个类来创建测试用例

程序中大多数的函数方法是封装在类里面的,所以我们要怎样针对一个类来创建测试用例?其实和函数一样的,只不过一个类里面封装的可能是一个较短的流程,我们怎样对这个流程进行一个完整的单元测试。
举个例子:
比如我们要针对下面的这个用于问卷调查的类进行单元测试,这个类中包含了一整个问卷调查的流程


```python
class AnonymousSurvey:

        def __init__(self, question):
            """初始化"""
                self.question = question
                self.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}")

正常的问卷调查流程,首先我们要测试问卷调查的问题是否和我们设置的问题一致;存储的调查结果是否和实际填写的回答一致;最后的总的调查结果是否包含了所有用户的回答,有了上面的思路我们针对上面的问卷调查类来编写一个测试类

class TestAnonymousSurvey(unittest.TestCase):

        def setUp(self):
        """ unittest.TestCase 类包含的方法setUp() 让我们只需创建这些对象一次,就能在每            个测试方法中使用。如果在TestCase类中包含了方法setUp()Python将先运行它,再运行各个以test_ 打头的方法。这样,在你编写的每个测试方法中,都可使用在方法setUp()中创建的对象 """
                self.question = "What language did you first learn to speak?"
                self.survey = AnonymousSurvey(self.question)
                self.responses = ['English', 'Spanish', 'Mandarin']

        def test_store_response(self):
                survey = AnonymousSurvey(self.question)
                survey.store_response('English')
                """判断回答的调查问卷的'English',是否和存储的答案一致,这里因为是第一个回答所以直接将English和responses里面的第一个元素进行对比了,实际上应该使用assertIn方法来判断"""
                self.assertEqual(survey.responses[0],'English')

if __name__ =='__main__':
        unittest.main()

上面我们测试的时候只是针对单个回答,在实际情况中调查问卷也有多选的情况,这种我们也要考虑到多个回答时数据能否正确存储。所以我们再往这个测试类中添加一个多选项的测试方法
#首先我们要先将之间的测试类中的self.responses改成一个包含三个答案的list

def setup(self):
    self.responses = ['English', 'Spanish', 'Mandarin']
def test_store_three_response(self):
    survey = AnonymousSurvey(self.question)
    for response in self.responses:
        survey.store_response(response)
        for response in self.responses:
            self.assertIn(response, survey.responses)

此时再次运行程序:

两个测试case都测试通过,证明单项选择和多项选择都可以妥善的存储。
以上只是一个初步入门简单的针对函数和类做的一个单元测试,如果想深入了解的话还需要去深挖unittest框架中TestCae基类中包含的方法,并且灵活运用到平常的项目中去。如果想更多的了解基类中的一些方法和断言请移步官网:https://docs.python.org/zh-cn/3/library/unittest.html#classes-and-functions

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值