0


Python 单元测试详解:Unittest 框架的应用与最佳实践

Python 单元测试详解:Unittest 框架的应用与最佳实践

文章目录

本文介绍了如何使用 Python 的原生测试框架 Unittest 进行单元测试,从基础的测试编写到复杂的场景覆盖。首先,展示了如何在不使用测试框架的情况下手动调试代码,并对比了使用 Unittest 的好处。文章通过多个实际示例,介绍了如何编写测试用例、处理断言和异常、分离测试文件以及执行多功能测试。同时,探讨了 Unittest 提供的常用断言方法,并展示了如何单独测试某个功能。最后,总结了编写高效单元测试的建议,使开发者在项目中更好地保证代码质量。

一 什么是 Unittest

unittest 是 Python 原生的测试框架。

1 不使用 Unittest 测试框架
defmy_div(a, b):return a / b
# ZeroDivisionError: division by zero
my_div(1,0)

程序抛出错误。不用测试框架手动运行调试,即边开发边调试,这种方式比较适合以下场景。

  • 项目整体规模较小
  • 项目功能数量较少
  • 项目功能之间相对独立
2 使用 Unittest 测试框架

TestFunc 继承 unittest.TestCase ,使用 unittest.main() 调用单元测试就写好了。

以下是运行没问题的单元测试。

# TestFunc 继承 unittest.TestCaseclassTestFunc(unittest.TestCase):deftest_div(self):# 运行之后 OK
        self.assertEqual(2, my_div(2,1))
        self.assertEqual(-2, my_div(2,-1))if __name__ =='__main__':
    print_hi('单元测试')
    unittest.main()# 运行之后# Ran 1 test in 0.000s# OK

以下是运行抛异常的单元测试。

# TestFunc 继承 unittest.TestCaseclassTestFunc02(unittest.TestCase):deftest_div(self):# 这里后面我填了一个 1 纯粹是为了占一个位置,2/0 != 1,你知道的,# 后面我们再介绍更优雅的写法# 运行之后 FAILED (errors=1)
        self.assertEqual(1, my_div(2,0))if __name__ =='__main__':
    print_hi('单元测试')
    unittest.main()# 运行之后 FAILED (errors=1)

二 unittest 使用建议

假如要开发一个:输入 1 返回 2,输入 - 1 返回 3 ,输入其他任何数,返回 1 的程序。

1 先写测试 case 后写测试逻辑

建议先写 unittest 当中的 case,再写你要封装的函数 my_func03。

defmy_func03(a):# 逻辑先空在这里returnNoneclassTestFunc03(unittest.TestCase):deftest_func(self):
         self.assertEqual(2, my_func03(1))
         self.assertEqual(3, my_func03(-1))for i inrange(-100,100):if i ==1or i ==-1:continue
             self.assertEqual(1, my_func03(i))
2 测试文件以 _test.py 结尾

建议一个 py 文件一个 test ,比如文件是 yourpython.py ,则单元测试可以命名为 yourpython_test.py

三 多个功能测试

一个类 TestFunc04 中定义多个测试函数。

defmy_func1(a):if a ==1:return2elif a ==-1:return3else:return1defmy_func2(b):if b !="yes":raise ValueError("you can only say yes!")else:returnTrueclassTestFunc04(unittest.TestCase):deftest_func1(self):
        self.assertEqual(2, my_func1(1))
        self.assertEqual(3, my_func1(-1))for i inrange(-100,100):if i ==1or i ==-1:continue
            self.assertEqual(1, my_func1(i))deftest_func2(self):
        self.assertTrue(my_func2("yes"))with self.assertRaises(ValueError):
            my_func2("nononono")

四 用 Python 命令执行测试

$ python -m unittest 单元测试.py

五 断言 assert 常用方法

在 unittest 的模块中有很多丰富的测试方法函数。
assert 断言含义assertEqual(a, b)

a == b

assertNotEqual(a, b)

a != b

assertTrue(condition)condition 是不是 TrueassertFalse(condition)condition 是不是 FalseassertGreater(a, b)

a > b

assertGreaterThan(a, b)

a >= b

assertLess(a, b)

a < b

assertLessEqual(a, b)

a <= b

assertIs(a, b)

a is b

,a 和 b 是不是同一对象assertIsNot(a, b)

a is not b

,a 和 b 是不是不同对象assertIsNone(a)

a is None

,a 是不是 NoneassertIsNotNone(a)

a is not None

,a 不是 None?assertIn(a, b)

a in b

, a 在 b 里面?assertNotIn(a, b)

a not in b

,a 不在 b 里?assertRaises(err)通常和 with 一起用,判断 with 里的功能是否会报错(上面练习有用到过)

六 测试单独的功能

测试类 TestFunc05 中的 test_func1 方法。常用的两种方式。

1 第一种

使用 TestSuite() 和 TextTestRunner()

# 第一种,使用 TestSuite() 和 TextTestRunner()classTestFunc05(unittest.TestCase):deftest_func1(self):
        self.assertEqual(2, my_func1(1))
        self.assertEqual(3, my_func1(-1))for i inrange(-100,100):if i ==1or i ==-1:continue
            self.assertEqual(1, my_func1(i))deftest_func2(self):
        self.assertTrue(my_func2("yes"))with self.assertRaises(ValueError):
            my_func2("nononono")# 定义一个 suite 替换 unittest.main()
suite = unittest.TestSuite()
suite.addTest(TestFunc04('test_func1'))
unittest.TextTestRunner().run(suite)
2 第二种
# 第二种,Python 的命令来执行不同的 test
$ python -m unittest 单元测试.TestFunc05.test_func1
$ python -m unittest 单元测试.TestFunc05.test_func2

七 完整代码示例

# This is a sample Python script.import unittest

# Press ⌃R to execute it or replace it with your code.# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.defprint_hi(name):# Use a breakpoint in the code line below to debug your script.print(f'Hi, {name}')# Press ⌘F8 to toggle the breakpoint.# 什么是 Unittest# 不用 Unittest 单元测试,可能是先运行试试# ZeroDivisionError: division by zero# 这种方式比较适合# 小型项目,# 没有多少个功能的项目,# 而且项目功能之间并不会有任何联系。# my_div(1, 0)defmy_div(a, b):return a / b

    # 使用 unittest# TestFunc 继承 unittest.TestCase# class TestFunc(unittest.TestCase):#     def test_div(self):#         # 运行之后 OK#         self.assertEqual(2, my_div(2, 1))#         self.assertEqual(-2, my_div(2, -1))# class TestFunc02(unittest.TestCase):#     def test_div(self):#         # 这里后面我填了一个 1 纯粹是为了占一个位置,2/0 != 1,你知道的,#         # 后面我们再介绍更优雅的写法#         # 运行之后 FAILED (errors=1)#         self.assertEqual(1, my_div(2, 0))

    unittest.main()# unittest 规范# 假如要开发一个:输入 1 返回 2,输入 - 1 返回 3 ,输入其他任何数,返回 1 的程序# 建议先写 unittest 当中的 case,再写你要封装的函数 my_func03defmy_func03(a):# 逻辑先空在这里returnNone# class TestFunc03(unittest.TestCase):#     def test_func(self):#         self.assertEqual(2, my_func03(1))#         self.assertEqual(3, my_func03(-1))#         for i in range(-100, 100):#             if i == 1 or i == -1:#                 continue#             self.assertEqual(1, my_func03(i))# 建议一个 py 文件一个 test ,比如文件是 yourpython.py ,则单元测试可以命名为 yourpython_test.py# 有时候要测试多个功能defmy_func1(a):if a ==1:return2elif a ==-1:return3else:return1defmy_func2(b):if b !="yes":raise ValueError("you can only say yes!")else:returnTrueclassTestFunc04(unittest.TestCase):deftest_func1(self):
        self.assertEqual(2, my_func1(1))
        self.assertEqual(3, my_func1(-1))for i inrange(-100,100):if i ==1or i ==-1:continue
            self.assertEqual(1, my_func1(i))deftest_func2(self):
        self.assertTrue(my_func2("yes"))with self.assertRaises(ValueError):
            my_func2("nononono")# 用 Python 命令执行测试# python -m unittest 单元测试.py# 能测哪些 assert,在 unittest 的模块中有特别丰富的测试方式,常用的方法# 。。。# 想测单独的功能# 第一种,使用 TestSuite() 和 TextTestRunner()classTestFunc05(unittest.TestCase):deftest_func1(self):
        self.assertEqual(2, my_func1(1))
        self.assertEqual(3, my_func1(-1))for i inrange(-100,100):if i ==1or i ==-1:continue
            self.assertEqual(1, my_func1(i))deftest_func2(self):
        self.assertTrue(my_func2("yes"))with self.assertRaises(ValueError):
            my_func2("nononono")# 定义一个 suite 替换 unittest.main()
suite = unittest.TestSuite()
suite.addTest(TestFunc04('test_func1'))
unittest.TextTestRunner().run(suite)# 第二种,Python 的命令来执行不同的 test# python -m unittest 单元测试.TestFunc05.test_func2# python -m unittest 单元测试.TestFunc05.test_func1# Press the green button in the gutter to run the script.if __name__ =='__main__':
    print_hi('单元测试')# See PyCharm help at https://www.jetbrains.com/help/pycharm/

复制粘贴并覆盖到你的 main.py 中运行,运行结果如下。

Testing started at 16:02 ...
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

Ran 4 tests in 0.001s

OK

八 源码地址

代码地址:

国内看 Gitee 之 单元测试.py

国外看 GitHub 之 单元测试.py

引用 莫烦 Python


本文转载自: https://blog.csdn.net/u014394049/article/details/142303705
版权归原作者 敲代码不忘补水 所有, 如有侵权,请联系我们删除。

“Python 单元测试详解:Unittest 框架的应用与最佳实践”的评论:

还没有评论