unittest介绍及使用
unittest是python的自动化测试框架:
Unittest框架包含以下部分:
TestCate(测试用例)
TestSuite(测试套件,把多个TestCase集成到一个测试TestSuite)
TestRunner(执行测试用例)
TestLoader(自动从代码中加载多个测试用例TestCase)
Fixture(unitTest特性)
使用unittest框架:
能够组织多个用例去执行
提供丰富的断言方法
能够生成测试报告(由于生成的测试报告捡漏,选择使用其他插件实现)
TestCase
实现步骤:
- 导包: import unittest
- 定义测试类: 新建测试类必须继承unittest.TestCase
- 定义测试方法: 测试方法名称必须以test开头
- 调用unittest.main()执行测试用例
import unittest
def my_sum(a,b):
return a+b
class MyTest(unittest.TestCase):
#测试用例01
def test_01(self):
print(my_sum(3,2))
#测试用例02
def test_02(self):
print(my_sum(1,6))
#测试用例03
def test_03(self):
print(my_sum('abc',9))
#测试用例04
def test_04(self):
print(my_sum(0,4))
TestSuite
TestSuite可以把多个测试用例整合成一个测试套件
使用方法:
(1).导包: import unittest
(2).导入测试用例文件: 用例文件命名应符合变量命名规则
(3).实例化TestSuite对象: suite = unittest.TestSuite()
(4).调用对象addTest方法: suite.addTest(用例文件名.类名("方法名"))
# 预置条件:
- 创建demo1.py, 内部编写测试用例
- 创建demo2.py, 内部使用测试套件, 加载多个测试用例
#demo1.py
import unittest
def my_sum(a,b):
return a+b
class MyTest(unittest.TestCase):
#测试用例01
def test_01(self):
print(my_sum(3,2))
#测试用例02
def test_02(self):
print(my_sum(1,6))
#测试用例03
def test_03(self):
print(my_sum("abc",9))
#测试用例04
def test_04(self):
print(my_sum(0,4))
#demo02.py
improt unittest
import demo1
#实例化TestSuite对象
suite=unittest.TestSuite()
suite.addTest(demo01.MyTest("test_01"))
suite.addTest(demo01.MyTest('test_03')) # 注意: 此操作只是加载测试用例, 并未执行
makeSuite
#makeSuite使用示例
import unittest
import demo01
#实例化TestSuite对象
suite=unittest.TestSuite()
suite.addTest(unittest.makeSuite(demo01.MyTest))# 加载demo1中MyTest中所有用例
TestRunner
#makeSuite使用示例
import unittest
import demo01
#实例化TestSuite对象
suite=unittest.TestSuite()
suite.addTest(unittest.makeSuite(demo01.MyTest))# 加载demo1中MyTest中所有用例
runner=unittest.TextTestRunner()
runner.run(suite)
TestLoader
TestLoader可以更方便加载用例
使用步骤:
import unittest
#实例化TestLoader对象,调用discover方法加载demo01.py中全部的用例
suite=unittest.TestLoader().discover('./',"demo01.py")
runner=unittest.TextTestRunner()
runner.run(suite)
TestSuite 与 TestLoader 区别
TestSuite 需要手动添加测试用例(可以添加测试类,也可以添加测试类中某 个测试方法)
TestLoader 搜索指定目录下指定开头.py 文件,并添加测试类中的所有的测试 方法,不能指定添加测试方法
Fixture
# 了解Fixture:
#Fixture 是一个概述,对一个测试用例环境的初始化和销毁就是一个Fixture。
#以开发的视角去理解, Fixture就像是Flask框架中的钩子.
#特定的方法, 在测试用例执行前后进行执行.
# Fixture存在控制级别:
#不同的级别决定了执行的作用范围和时机
# - 方法级别;
# - 类级别;
# - 模块级别;
方法级别
初始化(前置处理): def setUp(self) -->
首先自动执行;- 销毁(后置处理): def tearDown(self) -->
最后自动执行;运行于测试方法的始末,即:运行一次测试方法就会运行一次setUp和tearDown
import unittest
class my_test01(unittest.TestCase):
def setUp(self):
print("setUP 执行")
def tearDown(self):
print("teardown 执行")
def test_01(self):
print("my_test01 的 test01")
def test_02(self):
print("my_test01 的 test02")
类级别
- 初始化(前置处理): @classmethod def setUpClass(cls): -->
- 首先自动执行- 销毁(后置处理): @classmethod def tearDownClass(cls): -->
- 最后自动执行运行于测试类的始末,即:每个测试类只会运行一次setUpClass和tearDownClass
import unittest
class my_test01(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setUPClass 执行")
@classmethod
def tearDownClass(cls):
print("tearDownClass 执行")
def setUp(self):
print("setUP 执行")
def tearDown(self):
print("teardown 执行")
def test_01(self):
print("my_test01 的 test01")
def test_02(self):
print("my_test01 的 test02")
模块级别
- 初始化(前置处理): def setUpModule() -->
- 首先自动执行- 销毁(后置处理): def tearDownModule() -->
- 最后自动执行运行于整个模块的始末,即:整个模块只会运行一次setUpModule和tearDownModule
总结
- 必须继承 unittest.TestCase 类,setUp、tearDown 才是一个 Fixture;
- setUp,tearDown:如果一个类中有多个测试用例,每执行一个测试用例之 前会调用一次 setUp,之后会调用一次 tearDown;
- setUpClass,tearDownClass:如果一个类中有多个测试用例,执行所有测试用例之前只会 调用一次 setUpClass,之后只会调用一次 tearDownClass;
- setUpModule,tearDownModule:只在 import 导入这个模块时会调用一次 setUpModule,模块使用完成之后会调用一次 tearDownModule;
- setUpXXX:一般做初始化工作;
- tearDownXXX:一般做结束工作;
unittest 断言
常用断言:
序号 | 断言方法 | 断言描述 |
---|---|---|
1 | assertTrue(expr, msg=None) | 验证 expr 是 true,如果为 false,则 fail |
2 | assertFalse(expr, msg=None) | 验证 expr 是 false,如果为 true,则 fail |
3 | assertEqual(expected, actual, msg=None) | 验证 expected==actual,不等则 fail |
4 | assertNotEqual(first, second, msg=None) | 验证 first != second, 相等则 fail |
5 | assertIsNone(obj, msg=None) | 验证 obj 是 None,不是则 fail |
6 | assertIsNotNone(obj, msg=None) | 验证 obj 不是 None,是则 fail |
7 | assertIn(member, container, msg=None) | 验证是否 member in container |
8 | assertNotIn(member, container, msg=None) | 验证是否 member not in container |
使用步骤:
import unittest
def my_sum(a,b):
return a+b
class my_test(unittest.TestCase):
def test01(self):
num=my_sum(1,3)
#如果 num为4 正确
self.assertEqual(4,num)
def test02(self):
num=my_sum(4.3)
#如果num为4 正确
self.assertEqual(4,num)
def test03(self):
num=my_sum(1,2)
#如果num在列表中 正确
self.assertIn(num,[1,2,3,4,5])
参数化
#安装pip install parameterized#使用
- 导包:
from parameterized import parameterized;
- 使用@parameterized.expand 装饰器可以为测试函数的参数进行参数化;
-
#方法一
import unittest
from parameterized import parameterized
def my_sum(a,b):
return a+b
class Testmy_sum(unittest.TestCase):
@parameterized.expand([(1,1,2),(1,0,1),(0,0,0)])
def test_01(self,x,y,expect)
result=my_sum(x,y)
self.assertEqual(result,expect)
#方法二
import unittest
from parameterized import parameterized
def my_sum(a,b):
return a+b
#构建测试数据
def build_data():
return[(1,1,2),(1,0,1),(0,0,0)]
class Testmy_sum(unittest.TestCase):
@parameterized.expand(build_data)
def test_03(self, x, y, expect):
result = my_sum(x, y)
self.assertEqual(result, expect)