前言
在本文中,我们将探讨Python的UnitTest模块,这是一个内置的单元测试框架,用于编写和组织测试用例,验证代码的正确性,以及生成详细的测试报告。通过学习UnitTest,我们将理解如何有效地使用它来提升我们的编程效率和代码质量。
个人主页:尘觉主页
个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力
在csdn获奖荣誉: csdn城市之星2名
Java全栈群星计划top前5
端午大礼包获得者
阿里云专家博主
亚马逊DyamoDB结营
欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,感谢大家的观看
如果文章有什么需要改进的地方还请大佬不吝赐教 先在次感谢啦
UnitTest 是 Python 自带的一个单元测试框架,用它来做单元测试。
为什么使用UnitTest框架?
- 能够组织多个用例去执行;
- 提供丰富的断言方法;
- 能够生成测试报告;
UnitTest 核心要素 :
- TestCase;
- TestSuite;
- TestRunner;
- TestLoader;
- Fixture;
TestCase 就是测试用例的意思。
示例:
我们可以定义一个实现加法操作的函数,并对该函数进行测试。
# 导包
import unittest
# 定义函数(方法)
def my_sum(i, j):
return i + j;
# 定义测试类 注:必须继承unittest.TestCase
class my_test(unittest.TestCase):
# 定义测试方法 注: 测试方法名称命名以 test 开头;
def test_01(self):
print(my_sum(1, 2))
def test_02(self):
print(my_sum(3, 4))
TestSuite 翻译过来的意识就是 测试套件,多条测试用例集合在一起,就是一个 TestSuite。
使用:
1、实例化(suite:为 TestSuite 实例化的名称,你可以叫a,b,c 都可以)
suite = unittest.TestSuite()
2、添加用例(ClassName:为类名;MethodName:为方法名)
suite.addTest(ClassName("MethodName"))
3、添加扩展:(搜索指定 ClassName 内 test 开头的方法并添加到测试套件中)
suite.addTest(unittest.makeSuite(ClassName))
注:
TestSuite 需要配合 TextTestRunner 才能被执行
TextTestRunner 是用来执行测试用例和测试套件的
使用:
实例化: runner = unittest.TextTestRunner()
执行: runner.run(suite) # suite:为测试套件名称
示例:
这里我们多写将测试类分模块。
Test01.py
# 导包
import unittest
# 定义函数(方法)
def my_sum(i, j):
return i + j;
# 定义测试类 my_test 注:必须继承unittest.TestCase
class my_test(unittest.TestCase):
# 定义测试方法 注: 测试方法名称命名以 test 开头;
def test_01(self):
print("结果:%s" % my_sum(1, 2)+" my_test的test_01")
def test_02(self):
print("结果:%s" % my_sum(3, 4)+" my_test的test_02")
Test02.py
# 导包
import unittest
# 定义函数(方法)
def my_sum(i, j):
return i + j;
class my_test02(unittest.TestCase):
def test_01(self):
print("结果:%s" % my_sum(1, 2)+" my_test02的test_01")
def test_02(self):
print("结果:%s" % my_sum(1, 2)+" my_test02的test_02")
Test.py :执行测试用例
import unittest
import Test01
import Test02
# 实例化TestSuite
suite = unittest.TestSuite()
# 添加用例
suite.addTest(Test01.my_test("test_01"))
# 添加 my_test02 类中所有 test 开头的方法
suite.addTest(unittest.makeSuite(Test02.my_test02))
# 实例化TextTestRunner
runner = unittest.TextTestRunner()
# 执行
runner.run(suite)
用来加载 TestCase 到 TestSuite 中,即加载满足条件的测试用例,并把测试用例封装成测试套件。
使用 unittest.TestLoader,通过该类下面的 discover()方法自动搜索指定目录下指定开头的.py 文件,并将查找到的测试用例组装到测试套件;
使用:
suite = unittest.TestLoader().discover(test_dir, pattern='test*.py')
test_dir: 为指定的测试用例的目录;
pattern:为查找的.py 文件的格式;
注:
如果文件名默认为’test*.py’ 也可以使用 unittest.defaultTestLoader 代替 unittest.TestLoader()
示例:
import unittest
# 实例化 TestLoader
suite = unittest.TestLoader().discover("./", "test0*.py")
# 实例化TextTestRunner
runner = unittest.TextTestRunner()
# 执行
runner.run(suite)
TestSuite 与 TestLoader 区别
Fixture 是一个概述,对一个测试用例环境的初始化和销毁就是一个Fixture 。
Fixture有三个控制级别:
在TestCase,也就是测试用例所在的class中定义方法,如果一个TestCase中有多个测试用例,那么setUp和tearDown就会被自动调用多次。
使用:
- 初始化(前置处理): def setUp(self) --> 首先自动执行;
- 销毁(后置处理): def tearDown(self) --> 最后自动执行;
运行于测试方法的始末,即:运行一次测试方法就会运行一次 setUp 和tearDown
示例:
# 导包
import unittest
# 定义函数(方法)
def my_sum(i, j):
return i + j;
# 定义测试类 my_test 注:必须继承unittest.TestCase
class my_test(unittest.TestCase):
# 初始化方法
def setUp(self):
print("setUP 执行初始化")
# 销毁方法
def tearDown(self):
print("tearDown 执行销毁")
# 定义测试方法 注: 测试方法名称命名以 test 开头;
def test_01(self):
print("结果:%s" % my_sum(1, 2) + " my_test的test_01")
def test_02(self):
print("结果:%s" % my_sum(3, 4) + " my_test的test_02")
不管类中有多少方法,一个类开始的时候自动调用函数,结束的之后自动调用函数。
使用:
初始化(前置处理): @classmethod def setUpClass(cls): --> 首先自动执行
- 销毁(后置处理): @classmethod def tearDownClass(cls): --> 最后自动执行
运 行于 测试 类的 始末 , 即: 每个 测试类只会运行 一次 setUpClass 和 tearDownClass
# 导包
import unittest
# 定义函数(方法)
def my_sum(i, j):
return i + j;
# 定义测试类 my_test 注:必须继承unittest.TestCase
class my_test(unittest.TestCase):
# 初始化
@classmethod
def setUpClass(cls):
print("setUP 执行初始化")
# 销毁方法
@classmethod
def tearDownClass(cls):
print("tearDown 执行销毁")
# 定义测试方法 注: 测试方法名称命名以 test 开头;
def test_01(self):
print("结果:%s" % my_sum(1, 2) + " my_test的test_01")
def test_02(self):
print("结果:%s" % my_sum(3, 4) + " my_test的test_02")
不管py文件中有多少个类,以及类中有多少方法,只自动执行一次
使用:
- 初始化(前置处理): def setUpModule(): --> 首先自动执行
- 销毁(后置处理): def tearDownModule(): --> 最后自动执行
# 导包
import unittest
# 定义函数(方法)
def my_sum(i, j):
return i + j;
# 模块级
def setUpModule():
print("setUpModule自动调用了")
# 模块级
def tearDownModule():
print("tearDownModule自动调用了")
# 定义测试类 my_test 注:必须继承unittest.TestCase
class my_test(unittest.TestCase):
# 定义测试方法 注: 测试方法名称命名以 test 开头;
def test_01(self):
print("结果:%s" % my_sum(1, 2) + " my_test的test_01")
def test_02(self):
print("结果:%s" % my_sum(3, 4) + " my_test的test_02")
# 定义测试类 my_test02
class my_test02(unittest.TestCase):
def test_01(self):
print("结果:%s" % my_sum(1, 2) + " my_test02的test_01")
def test_02(self):
print("结果:%s" % my_sum(1, 2) + " my_test02的test_02")
- 必须继承 unittest.TestCase 类,setUp、tearDown 才是一个 Fixture;
- 方法级:setUp,tearDown:如果一个类中有多个测试用例,每执行一个测试用例之前会调用一次 setUp,之后会调用一次 tearDown;
- 类级:setUpClass,tearDownClass:如果一个类中有多个测试用例,执行所有测试用例之前只会调用一次 setUpClass,之后只会调用一次 tearDownClass;
- 模块级:setUpModule,tearDownModule:只在 import 导入这个模块时会调用一次 setUpModule,模块使用完成之后会调用一次 tearDownModule;
- setUpXXX:一般做初始化工作; tearDownXXX:一般做结束工作;
让程序代替人为判断测试程序执行结果是否符合预期结果的过程。
为什么要学习断言呢?
因为自动化脚本在执行的时候一般都是无人值守状态,我们不知道执行结果是否符合预期结果,所以我们需要让程序代替人为检测程序执行的结果是否符合预期结果,这就需要使用断言。
UnitTest 中提供了非常丰富的断言方法,复杂的断言方法在自动化测试中几乎使用不到,所以我们只需要掌握几个常用的即可。
常用的 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 |
断言方法已经在 unittest.TestCase 类中定义好了,而且我们自定义的测试类已经继承了 TestCase,所以在测试方法中直接调用即可。
# 导包
import unittest
# 定义函数(方法)
def my_sum(i, j):
return i + j;
# 定义测试类 my_test 注:必须继承unittest.TestCase
class my_test(unittest.TestCase):
# 定义测试方法 注: 测试方法名称命名以 test 开头;
def test_01(self):
num = my_sum(1, 2)
# 如果 num为4,正确
self.assertEqual(3, num);
def test_02(self):
num = my_sum(3, 4)
# 如果 num为7,正确
self.assertEqual(7, num);
def test_03(self):
num = my_sum(1, 2)
# 如果 num在列表中,正确
self.assertIn(num,[1,2,3,4,5])
上面的测试用例都存在一个问题,都是一条测试数据定义一个测试函数,代码冗余度太高。
我们可以通过参数化的方式来传递数据,从而实现数据和脚本分离。
并且可以实现用例的重复执行。unittest测试框架,本身不支持参数化,但是可以通过安装 unittest扩展插件 parameterized 来实现。
方式一:
我们可以直接打开命令提示符输入:pip install parameterized
方式二 :
使用PyCharm 安装,直接看图
方式一:
import unittest
from parameterized import parameterized
def my_sum(i, j):
return i + j
class my_test(unittest.TestCase):
# a是调用my_sum的第一个参数
# b是调用my_sum的第二个参数
# c是预期结果
@parameterized.expand([(1, 2, 3), (5, 6, 110), (-1, 3, 2)])
def test_001(self, i, j, k):
# 定义变量num得到my_sum函数的返回值
num = my_sum(i, j)
# num1里存放的是实际结果,k是预期结果
self.assertEqual(num, k)
# 实际结果与预期结果相符,代表测试用例测试通过
# 不相符代表测试用例测试失败
方式二:
就是直接定义好一个列表,列表里面有元组。
data =[(1,2,3),(5,6,110),(-1,3,2)]
方式三:
就是定义一个函数(方法),然后直接返回元组。
对于一些未完成的或者不满足测试条件的测试函数和测试类,可以跳过执行。
使用方式:
@unittest.skip(‘代码未完成’):直接将测试函数标记成跳过
@unittest.skipIf(condition, reason):根据条件判断测试函数是否跳过
示例:
import unittest
# 定义西数《方法)
def my_sum(i, j):
return i + j
sum = 70
@unittest.skip("代码未完成")
class my_test(unittest.TestCase):
def test_01(self):
print("结果: %s" % my_sum(1, 2) + "my_test2的test_1")
def test_02(self):
print("结果:%s" % my_sum(1, 2) + "my_test2的test_2")
class my_testo2(unittest.TestCase):
@unittest.skipIf(sum < 60, '你的分数得大于60')
def test_01(self):
print('及格')
@unittest.skip('不及格')
def test_02(self):
print('不及格')
HTML 测试报告就是执行完测试用例后,以 HTML(网页)方式将执行结果生成报告。
为什么要生产测试报告?
因为测试报告是本次测试结果的体现形态,然后测试报告内包含了有关本次测试用例的详情;
HTML 生成报告方式
一种是TextTestRunner (UnitTest 自带),另外的就是其他的第三方模板HTMLTestRunner。
首先我们先来看看TextTestRunner如何生成测试报告的。
import unittest
# 生成测试套件
suite = unittest.TestLoader().discover("./", "test0*.py")
# 以只写方式打开测试报告文件
f = open("C:/Users/jie/Desktop/test.txt", "w", encoding="utf-8")
# 实例化TextTestRunner stream为open函数打开的文件流; verbosity 为不同模板编号
runner = unittest.TextTestRunner(stream=f,verbosity=2)
# 执行
runner.run(suite)
# 关闭
f.close()
结果
我们再来看看HTMLTestRunner 测试报告
首先要安装HTMLTestRunner,这里要注意的是由于HTMLTestRunner是一个第三方的unittest HTML报告库,用pip是死活安装不了的,得去网上下载HTMLTestRunner.py放到存放python源代码的Lib目录下。大家也可以用我下好的。
在绑定资料里面
import unittest
from HTMLTestRunner import HTMLTestRunner
# 生成测试套件
suite = unittest.TestLoader().discover("./", "test*.py")
# 以只写方式打开测试报告文件
f = open("C:/Users/jie/Desktop/test01.html", "wb")
# 实例化 HTMLTestRunner 对象 stream:open 函数打开的文件流; title:[可选参数],为报告标题; description:[可选参数],为报告描述信息;比如操作系统、浏览器等版本;
runner = HTMLTestRunner(stream=f, title="自动化测试报告", description="Chrome 浏览器")
# 执行
runner.run(suite)
# 关闭
f.close()
在本文中,我们深入探讨了Python的UnitTest模块,它是Python内置的一个强大的单元测试框架。通过定义测试用例,我们可以对特定的功能或方法进行细致的测试。这些测试用例可以组织成测试套件,然后使用TextTestRunner来执行并生成详细的测试报告。
我们也学习了如何使用断言来验证代码的行为是否符合预期。这些断言可以检查各种条件,如变量是否等于预期值,或者函数是否抛出了预期的异常等。
总的来说,UnitTest是一个非常有用的工具,它可以帮助我们确保代码的质量和正确性。通过编写单元测试,我们可以减少代码错误,提高代码的可维护性,并提高我们的编程效率。
希望这篇文章能帮助你更好地理解Python的UnitTest框架。如果你有任何问题或需要进一步的讨论,欢迎在下方留言。
热门专栏推荐
想学习vue的可以看看这个
java基础合集
数据库合集
redis合集
nginx合集
linux合集
手写机制
微服务组件
spring_尘觉
springMVC
mybits
等等等还有许多优秀的合集在主页等着大家的光顾感谢大家的支持
欢迎大家加入我的社区 尘觉社区
文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论
希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力