编辑
2024-07-07
📘总结-保持好奇心
00
请注意,本文编写于 347 天前,最后修改于 225 天前,其中某些信息可能已经过时。

目录

测试框架Unittest的用法
1.什么是单元测试?
2.为什么要做单元测试?
3. Unittest框架及原理
4. unittest的断言
5. TestCase测试用例
6. TestFixure测试夹具
7. TestSuite测试套件
8. TestRunner执行用例

测试框架Unittest的用法

1.什么是单元测试?

单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类,一般是开发来做的,按照测试阶段来分,就是单元测试、集成测试、系统测试以及验证测试。

2.为什么要做单元测试?

  • 单元测试之后,才是集成测试,单个的功能模块测试通过之后,才能把单个功能模块集成起来做成测试,为了从底层发现bug,单元测试时可以减少合成后出现的问题
  • 越早发现bug越好,这样可以早点发现问题,不然问题累计到后面,很可能会因为一个做错了而导致整个模块甚至更大范围的推倒重来,对于时间和经费来说,是非常浪费的。
  • 对于测试来说,单元测试就是为了执行用例,输入测试数据->输出测试结果

3. Unittest框架及原理

unittest框架最核心的4个概念:

1. test case: 就是我们的测试用例,unitest中提供了一个基本类TestCase,可以用来创建新的测试用例,一个Testcase的实例就是一个测试用例,unittest中测试用例方法都是以test开头的,且执行顺序会按照方法名的ASCII值排序。 2. test fixure 测试夹具,用于测试用例环境的搭建和销毁。即用例测试前准备环境的搭建(SetUp前置条件),测试后环境的还原(TearDown后置条件),比如测试前需要登录获取token等就是测试用例需要的环境,运行完后执行下一个用例前需要还原环境,以免影响下一条用例的测试结果。 3. test suite 测试套件,用来把需要一起执行的测试用例集中放到一起执行,相当于一个篮子。我们可以使用TestLoader来加载测试用例到测试套件中。 4. test runner 用来执行测试用例的,并返回测试用例的执行结果。它还可以用图形或者文本接口,把返回的测试结果更形象的展示出来,如:HTMLTestRunner.

4. unittest的断言

在python中assert的使用方法很简单,即assert表达式,提示信息,而unittest框架中也提供了一个自带的断言方式,主要有以下集中:

方法检查
assertEqual(a, b,msg=None)a==b
assertNotEqual(a, b)a !=b
assertTrue(x)bool(x) is True
assertFalse(x)Bool(x) is False
assertIs(a, b)a is b
assertIsNot(a, b)a is not b
assertIsNone(x)x is None
assertIsNotNone(x)x is not None
assertIn(a, b)a in b
assertNotIn(a, b)a not in b
assertIsInstance(a, b)isinstance(a,b)
assertNotIsInstance(a, b)not isinstance(a,b)

如果断言失败即不通过就会抛出一个AssertionError断言错误,成功则标识为通过,以上几种方式都有一个共同点,就是都有一个msg参数(表中只列了一个,其实都用),默认是None,即msg=None,如果指定msg参数的值,则将该信息作为失败的错误信息返回。

5. TestCase测试用例

步骤如下:

  • 导入unittest模块
  • 创建一个测试类,并继承unittest.TestCase()
  • 定义测试方法,方法名必须以test_开头
  • 调用unittest.main()方法来运行测试用例,unittest.main()方法会搜索该模块下所有以test开头的测试用例方法,并自动执行。

下面以注册功能为例,整个register.py就是注册功能的代码,没有前端界面,功能比较简单,只是方便用于演示,直接导入就可以使用:

python
# coding:utf-8 # register.py users = [{'username': 'test', 'password': '123456'}] def register(username, password1, password2): if not all([username, password1, password2]): return {"code": 0, "msg": "所有参数不能为空"} # 注册功能 for user in users: if username == user['username']: return {"code": 0, "msg": "该用户名已存在!"} else: if password1 != password2: return {"code": 0, "msg": "两次密码输入不一致!"} else: if 6 <= len(username) >= 6 and 6 <= len(password1) <= 18: users.append({'username': username, 'password': password2}) return {"code": 1, "msg": "注册成功"} else: return {"code": 0, "msg": "用户名和密码必须在6-18位之间"}
python
# coding:utf-8 # test_register.py import unittest from register import register # 导入被测试的代码 class TestRegister(unittest.TestCase): """注册接口测试用例类""" def test_register_success(self): """注册成功""" data = ("mikitest", "miki123", "miki123") # 测试数据 expected = {"code": 1, "msg": "注册成功"} # 预期结果 result = register(*data) # 把测试数据传到被测的代码,接收实际结果 self.assertEqual(expected, result) # 断言,预期和实际是否一致,一致即用例通过 def test_username_isnull(self): """注册失败-用户名为空""" data = ("", "miki123", "miki123") expected = {"code": 0, "msg": "所有参数不能为空"} result = register(*data) self.assertEqual(expected, result) def test_username_lt6(self): """注册失败-用户名大于18位""" data = ("mikitestmikitestmikitest", "miki123", "miki123") expected = {"code": 0, "msg": "用户名和密码必须在6-18位之间!"} result = register(*data) self.assertEqual(expected, result) # 这条用例应该是不通过的,注册代码bug def test_pwd1_not_pwd2(self): """注册失败-两次密码不一致""" data = ("miki123", "test123", "test321") expected = {"code": 0, "msg": "两次密码输入不一致!"} result = register(*data) self.assertEqual(expected, result) # 如果直接运行这个文件,需要使用unittest中的main函数来执行测试用例 if __name__ == '__main__': unittest.main()

测试用例,一共4条用例,其中通过3条,不通过1条,不通过的是本身注册代码的bug。

6. TestFixure测试夹具

unittest的测试夹具有两种使用方式。

  • 一种是以测试方法为维度的setUp()和tearDown(),
  • 一种是以测试类维度的setUpClass()和tearDownClass()。以注册功能为例。
python
# test_register.py import unittest from register import register # 导入被测试的代码 class TestRegister(unittest.TestCase): """注册接口测试用例类""" def setUp(self): # 每条用例执行之前都会执行 print("用例{}开始执行--".format(self)) def tearDown(self): # 每条用例执行之后都会执行 print("用例{}执行结束--".format(self)) @classmethod # 指明这是个类方法以类为维度去执行的 def setUpClass(cls): # 整个测试用例类中的用例执行之前,会先执行此方法 print("-----setup---class-----") @classmethod def tearDownClass(cls): # 整个测试用例类中的用例执行完之后,会执行此方法 print("-----teardown---class-----") def test_register_success(self): """注册成功""" data = ("mikitest", "miki123", "miki123") # 测试数据 expected = {"code": 1, "msg": "注册成功!"} # 预期结果 result = register(*data) # 把测试数据传到被测的代码,接收实际结果 self.assertEqual(expected, result) # 断言,预期和实际是否一致,一致即用例通过 def test_username_isnull(self): """注册失败-用户名为空""" data = ("", "miki123", "miki123") expected = {"code": 0, "msg": "所有参数不能为空!"} result = register(*data) self.assertEqual(expected, result) # 如果直接运行这个文件,需要使用unittest中的main函数来执行测试用例 if __name__ == '__main__': unittest.main()

7. TestSuite测试套件

unittest.TestSuite()类来表示一个测试用例集,把需要执行的用例类或模块存到一起,常用的方法如下:

  • unittest.TestSuite()

    1. addTest():添加单个测试用例方法
    2. addTest([...]): 添加多个测试用例方法,方法名存在一个列表
  • unittest.TestLoader()

    1. loadTestsFromTestCase(测试类名):添加一个测试类
    2. loadTestsFromModule(模块名):添加一个模块类
    3. discover(测试用例的所在目录):指定目录去加载,会自动寻找整个目录下所有符合命名规则的测试用例。
python
# coding:utf-8 # run_test.py,与test_register.py、register.py同一目录下 import unittest import test_register # 第一步,创建一个测试套件 suite = unittest.TestSuite() # 第二步:将测试用例,加载到测试套件中 # 方式1,添加单条测试用例 # case = test_register.TestRegister("test_register_success") # 创建一个用例对象,注意:通过用例类去创建测试用例对象的时候,需要传入用例的方法名(字符串类型) # suite.addTest(case) # 添加用例到测试套件中 # 方式2,添加多条测试用例 # case1 = test_register.TestRegister("test_register_success") # case2 = test_register.TestRegister("test_username_isnull") # suite.addTest([case1, case2]) # 添加用例到测试套件中 # 方式3,添加一个测试用例类 # loader = unittest.TestLoader() # 创建一个加载对象 # suite.addTest(loader.loadTestsFromTestCase(test_register.TestRegister)) # 方式4,添加一个模块 loader = unittest.TestLoader() # 创建一个加载对象 suite.addTest(loader.loadTestsFromModule(test_register)) # 方式5,指定测试用例的所在的目录路径,进行加载 # loader = unittest.TestLoader() # suite.addTest(loader.discover(r"d:\learn\python"))

8. TestRunner执行用例

test runner顾名思义就是用来执行测试用例的,并且可以生成相应的测试报告。测试报告有两种展示形式,一种是text文本,一种是html格式。

html格式就是HTMLTestRunner了,HTMLTestRunner是python标准库的unittest框架的一个扩展,它可以生成一个直观清晰的HTML测试报告。使用的前提就是要下载HTMLTestRunner.py,下载完后放在Python的安装目录下的lib目录下的site-packages即可。

text文本相对于html来说比较简陋,与控制台输出的没有什么区别,也几乎没有人使用,这里不作演示。现在演示一下如何生成Html格式的测试报告:

本文作者:Eric

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!