Python 单元测试框架unittest
单元测试框架unittest
一般习惯在根目录下新建tests文件夹专门放我们的测试,这个测试文件夹要把它变成一个package,也就是里面放一个__init__.py,方便导包
被测文件:
class Vector: def __init__(self, x, y): self.x = x self.y = y def add(self, other): return Vector(self.x + other.x, self.y + other.y) def mul(self, factor): return Vector(self.x + factor, self.y + factor) def dot(self, other): return self.x * other.x +\ self.y * other.y def norm(self): return (self.x * self.x + self.y * self.y) ** 0.5
找测试项规则
每一个测试文件必须要是test_开头test_*.py
创建的测试类,必须要继承 unittest 模块的 TestCase 类,即 unittest.TestCase
测试类习惯以Test开头或Test结尾
测试类里面的测试方法必须以test_开头
注意点:每个测试方法当它有一个地方fail的时候,它就不会继续往下运行了
断言方法
其他断言方法见:https://docs.python.org/zh-cn/3/library/unittest.html?highlight=unittest
单独说一下assertRaises,修改一下被测文件的__Init__方法
# 被测文件 class Vector: def __init__(self, x, y): # x,y必须要是数 if isinstance(x, (int,float)) and isinstance(y,(int,float)): self.x = x self.y = y else: raise ValueError('not a number')
测试__init__函数是不是成功的raise了这个ValueError,写法如下
class TestVector(unittest.TestCase): def test_init(self): v = Vector(1, 2) self.assertEqual(v.x, 1) self.assertEqual(v.y, 2) with self.assertRaises(ValueError): v = Vector('1', '2') # 传了非数字,如果传入了数字那么就会fail
Test Fixture夹具
import unittest def setUpModule(): print("模块级别开始动作") def tearDownModule(): print("模块级别结束动作") class TestVector(unittest.TestCase): @classmethod # 测试类级别一定要加@classmethod def setUpClass(cls): print("类级别开始动作") @classmethod def tearDownClass(cls): print("类级别结束动作") def setUp(self): print("测试方法级别开始动作") def tearDown(self): print("测试方法级别结束动作") def test_init(self): v = Vector(1, 2) self.assertEqual(v.x, 1) self.assertEqual(v.y, 2)
跳过测试和预期失败
无条件地跳过装饰的测试,需要说明跳过测试的原因。
unittest.skip(reason)
如果条件为真,则跳过装饰的测试。
unittest.skipIf(condition, reason)
当条件为真时,执行装饰的测试
unittest.skipUnless(condition, reason)
不管执行结果是否失败,都将测试标记为失败。
unittest.expectedFailure()
测试用例
import unittest class TestVector(unittest.TestCase): @unittest.skip("直接跳过测试") def test_init(self): v = Vector(1, 2) self.assertEqual(v.x, 1) self.assertEqual(v.y, 2) # 这个测试不在window上运行 @unittest.skipIf(sys.platform == 'win32', '不支持windows系统') def test_add(self): v1 = Vector(1, 2) v2 = Vector(2, 3) v3 = v1.add(v2) self.assertEqual(v3.x, 3)
测试用例的执行顺序
多个测试目录 > 多个测试文件 > 多个测试类 > 多个测试方法(测试用例)
unittest默认根据ASCII码的顺序加载测试用例的(数字与字母的顺序为0~9,A~Z, a~z),所以 TestAdd 类会优先于 TestBdd 类被执行,test_aaa()方法会优先于 test_ccc()方法 被执行,也就是说,它不会按照测试用例的创建顺序从上到下执行的
除命名外,我们可以声明测试套件 TestSuite 类来控制测试用例的执行顺序,通过 addTest()方法按照一定的顺序来加载测试用例。
命令行执行测试
python -m unittest
python -m unittest tests.test_vector.TestVector.test_add
discover 方法
unittest 提供了可以共享的 defaultTestLoader 类,可以使用其子类或方法 创建实例,discover()方法就是其中之一
discover(start_dir,pattern='test*.py',top_level_dir=None)
start_dir :待测试的模块名或测试用例目录。
pattern='test*.py' :测试用例文件名的匹配原则。此处匹配文件名以“test”开头 的“.py”类型的文件,星号“*”表示任意多个字符。
top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,则默认为 None。
import unittest
# 定义测试用例的目录为当前目录中的 test_case/目录 test_dir = './test_case' suits = unittest.defaultTestLoader.discover(test_dir, pattern='test*.py')
if __name__ == '__main__': runner = unittest.TextTestRunner() runner.run(suits)
discover()方法会自动根据测试用例目录(test_dir)查找测试用例文件(test*.py),并 将找到的测试用例添加到测试套件中
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」