unittest:Python单元测试,守护你的代码

文摘   2024-11-01 20:32   广东  

▼点击下方卡片关注我

▲点击上方卡片关注我

要想写出靠谱的代码,单元测试就必不可少。真要说起来,咱们写代码就跟盖房子一样,单元测试就好比是房子的质量检测,每个砖块都得过关才行。Python标准库里的 unittest模块 就是一个特别好使的测试工具,今天咱们就一起来研究研究怎么用它来保证代码质量。


单元测试基本概念

单元测试说白了就是测试代码里最小的功能单元。比方说你写了个函数,那就得测测这个函数在各种情况下是不是都能正常工作。这么干有啥好处呢?bug早发现早治疗,代码重构也不怕改出问题。


来看个最基础的例子:


1# calculator.py

2def add(a, b):

3 return a + b

5def divide(a, b):

6 return a / b

对应的测试代码:


1# test_calculator.py

2import unittest

3from calculator import add, divide

5class TestCalculator(unittest.TestCase):

6 def test_add(self):

7 # 测试正数相加

8 self.assertEqual(add(1, 2), 3)

9 # 测试负数相加

10 self.assertEqual(add(-1, -1), -2)

12 def test_divide(self):

13 # 测试正常除法

14 self.assertEqual(divide(6, 2), 3)

15 # 测试除数为0的情况

16 with self.assertRaises(ZeroDivisionError):

17 divide(1, 0)

19if __name__ == '__main__':

20 unittest.main()

⚠️ 小贴士:


  • 测试方法名必须以test开头

  • 每个测试用例要够独立,不能互相影响

  • 测试要考虑边界条件和异常情况


断言方法大盘点

unittest提供了一堆好使的断言方法,这些都是测试武器库里的必备神器:


1def test_assertions(self):

2 # 判断相等

3 self.assertEqual(1 + 1, 2)

5 # 判断是否为True/False

6 self.assertTrue(isinstance(1, int))

7 self.assertFalse(2 > 3)

9 # 判断是否包含

10 self.assertIn(3, [1, 2, 3])

12 # 判断是否为None

13 self.assertIsNone(None)

测试夹具setUp和tearDown

有时候测试前要准备环境,测试后要清理现场,这时候就用得上这两个法宝了:


1class TestDatabase(unittest.TestCase):

2 def setUp(self):

3 # 测试前创建数据库连接

4 self.db = Database()

5 self.db.connect()

7 def tearDown(self):

8 # 测试后关闭连接

9 self.db.close()

11 def test_query(self):

12 result = self.db.execute(“SELECT * FROM users”)

13 self.assertIsNotNone(result)

⚠️ 小贴士:


  • setUp在每个测试方法前都会执行一次

  • tearDown即使测试失败也会执行

  • 数据库、文件操作记得在tearDown里清理


跳过测试和预期失败

代码改着改着,有些测试可能暂时跑不通,这时候可以暂时跳过:


1class TestFeatures(unittest.TestCase):

2 @unittest.skip(“暂时还没实现这个功能”)

3 def test_new_feature(self):

4 pass

6 @unittest.expectedFailure

7 def test_known_bug(self):

8 # 这个测试预期会失败

9 self.assertEqual(1/0, 1)

跟数据库这种外部系统打交道的测试,最好用mock来模拟,省事又靠谱:


1from unittest.mock import patch

3class TestUser(unittest.TestCase):

4 @patch('myapp.database.query')

5 def test_get_user(self, mock_query):

6 mock_query.return_value = {“id”: 1, “name”: “张三”}

7 user = get_user(1)

8 self.assertEqual(user['name'], “张三”)

⚠️ 小贴士:


  • mock对象要模拟原始对象的所有必要行为

  • mock记得验证是否被正确调用

  • 复杂的mock考虑用fixture来管理


写单元测试就是给代码上保险,多花点时间写测试,后面省心不少。代码改动时跑跑测试,哪里出问题一目了然。不过也别太死板,测试代码的投入要跟业务价值匹配,关键的核心逻辑一定要好好测。


往期回顾

◆ Pandas:Python数据分析的王者,掌握它就掌握了数据

◆ Python打造智能闹钟:为你定制早起计划

◆ 用Python实现区块链:从零开始

点赞分享


流向你

墨香玄
每日陪伴,聊聊关于车的这些事,理性与感性双管齐下,饮茶品文,有缘共谈!
 最新文章