引言
python小程序之UnitTest框架以及TestSuite书写方法
文章目录
- 引言
- 一、UnitTest框架
-
- [1.1 概念](#1.1 概念)
-
- [1.1.1 关键概念](#1.1.1 关键概念)
- [1.1.2 示例代码](#1.1.2 示例代码)
- [1.1.3 代码解释](#1.1.3 代码解释)
- [1.1.4 运行测试](#1.1.4 运行测试)
- [1.1.5 其他功能](#1.1.5 其他功能)
- [1.2 题目](#1.2 题目)
- [1.3 代码](#1.3 代码)
- [1.4 代码解释](#1.4 代码解释)
- 二、TestSuite书写方法
-
- [2.1 题目](#2.1 题目)
- [2.2 代码](#2.2 代码)
-
- [2.2.1 tool代码](#2.2.1 tool代码)
- [2.2.2 TestCase代码](#2.2.2 TestCase代码)
- [2.3 代码解释](#2.3 代码解释)
- 三、思考
-
- [3.1 UnitTest框架](#3.1 UnitTest框架)
- [3.2 TestSuite](#3.2 TestSuite)
一、UnitTest框架
1.1 概念
unittest
是 python 标准库中的一个测试框架,它提供了丰富的工具来编写和运行测试。unittest
框架的设计灵感来源于 Java 的 JUnit 测试框架,并且遵循了类似的测试组织方式
1.1.1 关键概念
-
测试用例 (TestCase) : 一个测试用例是包含一组相关测试的一个类。每个测试方法应该以
test
开头,以便unittest
能够自动识别它们 -
测试套件 (TestSuite): 一个测试套件是一个测试集合,可以包含多个测试用例或其它测试套件。这有助于将相关的测试组织在一起
-
测试加载器 (TestLoader): 用于从类中发现测试用例并加载到测试套件中
-
测试运行器 (TextTestRunner): 用于执行测试套件,并提供结果报告
-
断言 (Assertions): 断言是一些条件判断,用于验证程序的行为是否符合预期。如果断言失败,测试就会被标记为失败
-
setUp 和 tearDown: 这两个方法分别在每个测试方法之前和之后被调用,用来准备环境和清理资源
-
setUpClass 和 tearDownClass: 类级别的设置和清理方法,在所有测试开始前和结束后各执行一次
1.1.2 示例代码
python
import unittest
class TestStringMethods(unittest.TestCase):
def setUp(self):
# 在每个测试方法之前执行
self.name = "Alice"
print(f"Setting up for {self.name}")
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())
def test_split(self):
s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
# 检查当分隔符不在字符串中时的行为
with self.assertRaises(TypeError):
s.split(2)
def tearDown(self):
# 在每个测试方法之后执行
print(f"Tearing down for {self.name}")
if __name__ == '__main__':
unittest.main()
1.1.3 代码解释
TestStringMethods
继承自unittest.TestCase
setUp
方法在每个测试方法之前运行,用来初始化一些共享的变量或状态test_upper
,test_isupper
,test_split
是具体的测试方法。注意它们的名字都以test
开头tearDown
方法在每个测试方法之后运行,用来清理资源if __name__ == '__main__':
确保当这个脚本直接运行时,unittest.main()
将执行所有的测试
1.1.4 运行测试
可以通过命令行直接运行这个文件,或者在 IDE 中运行。unittest.main()
会查找所有的测试方法(以 test
开头的方法),然后依次执行它们,并显示测试结果:
1.1.5 其他功能
unittest
还支持更复杂的测试场景,例如参数化测试、跳过测试、预期失败等。此外,还可以结合其他工具如 coverage.py
来进行代码覆盖率分析,或者使用 nose
或 pytest
等第三方库来扩展测试功能
1.2 题目
学习UnitTest框架的书写方法
1.3 代码
python
import unittest
class Test_unittest(unittest.TestCase):
def test_first(self):
print('testcase1')
def test_second(self):
print('testcase2')
测试结果:
1.4 代码解释
-
导入
unittest
模块:pythonimport unittest
这行代码导入了
unittest
模块,它是 python 标准库中用于编写和运行测试的框架 -
定义测试类
Test_unittest
:pythonclass Test_unittest(unittest.TestCase):
定义了一个名为
Test_unittest
的测试类,并继承自unittest.TestCase
。这是unittest
框架的要求,所有的测试类都必须继承自unittest.TestCase
。这个类名可以随意命名,但通常建议以Test
开头,以便清晰地表明这是一个测试类 -
定义第一个测试方法
test_first
:pythondef test_first(self): print('testcase1')
- 定义了一个测试方法
test_first
- 注意,测试方法的名字必须以
test_
开头,这样unittest
才能识别并运行它 - 在这个方法中,打印了一条消息
'testcase1'
。这只是一个简单的示例,实际的测试方法通常会包含断言来验证代码的行为
- 定义了一个测试方法
-
定义第二个测试方法
test_second
:pythondef test_second(self): print('testcase2')
- 定义了另一个测试方法
test_second
。 - 同样,这个方法也以
test_
开头,并且在方法中打印了一条消息'testcase2'
- 定义了另一个测试方法
二、TestSuite书写方法
2.1 题目
- 在 tools 模块中定义 add 函数, 对两个数字进行求和计算
- 书写 TestCase 代码对 add() 进行测试
用例 1: 1, 2, 3
用例 2: 10, 20, 30
用例 3: 2, 3, 5
2.2 代码
2.2.1 tool代码
python
def addc(a, b):
return a+b
2.2.2 TestCase代码
python
from tools import addc
import unittest
class Testadd(unittest.TestCase):
def test_method1(self):
if addc(1,2) == 3:
print('测试通过')
else:
print('测试不通过')
def test_method2(self):
if addc(10,20) == 30:
print('测试通过')
else:
print('测试不通过')
def test_method3(self):
if addc(2,3) == 5:
print('测试通过')
else:
print('测试不通过')
输出结果:
2.3 代码解释
代码定义了一个简单的加法函数
addc
,并使用unittest
框架编写了几个测试方法来验证这个函数的正确性
-
定义
addc
函数:pythondef addc(a, b): return a + b
这个函数接受两个参数
a
和b
,并返回它们的和 -
导入
addc
函数:pythonfrom tools import addc
这行代码试图从
tools
模块中导入addc
函数。假设tools
模块中确实定义了addc
函数,并且该模块在当前目录或 python 路径中可用 -
导入
unittest
模块:pythonimport unittest
导入
unittest
模块,这是 python 标准库中用于编写和运行测试的框架 -
定义测试类
Testadd
:pythonclass Testadd(unittest.TestCase):
定义一个名为
Testadd
的测试类,并继承自unittest.TestCase
。这是unittest
框架的要求,所有的测试类都必须继承自unittest.TestCase
-
定义第一个测试方法
test_method1
:pythondef test_method1(self): if addc(1, 2) == 3: print('测试通过') else: print('测试不通过')
- 定义了一个测试方法
test_method1
。 - 使用
if
语句检查addc(1, 2)
是否等于 3 - 如果相等,打印
'测试通过'
;否则,打印'测试不通过'
- 定义了一个测试方法
-
定义第二个测试方法
test_method2
:pythondef test_method2(self): if addc(10, 20) == 30: print('测试通过') else: print('测试不通过')
- 定义了另一个测试方法
test_method2
- 使用
if
语句检查addc(10, 20)
是否等于 30 - 如果相等,打印
'测试通过'
;否则,打印'测试不通过'
- 定义了另一个测试方法
-
定义第三个测试方法
test_method3
:pythondef test_method3(self): if addc(2, 3) == 5: print('测试通过') else: print('测试不通过')
- 定义了第三个测试方法
test_method3
- 使用
if
语句检查addc(2, 3)
是否等于 5 - 如果相等,打印
'测试通过'
;否则,打印'测试不通过'
- 定义了第三个测试方法
三、思考
3.1 UnitTest框架
- 类名通常建议以
Test
开头,以便清晰地表明这是一个测试类 - 测试方法通常会包含断言来验证代码的行为
3.2 TestSuite
代码能够工作,但 unittest
提供了更强大的断言机制来替代简单的 if
语句。这样可以更好地报告测试结果,并提供更多的信息
python
import unittest
from tools import addc
class TestAdd(unittest.TestCase):
def test_method1(self):
self.assertEqual(addc(1, 2), 3)
def test_method2(self):
self.assertEqual(addc(10, 20), 30)
def test_method3(self):
self.assertEqual(addc(2, 3), 5)
-
使用
self.assertEqual
断言:self.assertEqual(expected, actual)
是unittest
中的一个断言方法,用于验证expected
是否等于actual
- 如果
expected
不等于actual
,测试将失败,并报告详细的错误信息
-
移除
print
语句:unittest
会自动报告测试的结果,不需要手动打印消息
-
如果某个测试失败,
unittest
会报告详细的错误信息,快速定位问题,类似下图