一、设计理念
unittest和pytest在设计理念上有很大不同。unittest是一个面向对象的单元测试框架,采用了传统的xUnit模式,通过继承TestCase类编写测试用例。pytest则致力于提供简单易用的API和插件,最大限度减少测试代码的编写量。pytest采用了更加Pythonic的编程风格,测试函数不需要继承某个类或者调用某个框架,只需要按照pytest的规则编写即可。
unittest示例代码:
import unittest class MathTest(unittest.TestCase): def test_add(self): self.assertEqual(1+1, 2) def test_mul(self): self.assertEqual(2*3, 6) if __name__ == '__main__': unittest.main()
pytest示例代码:
def test_add(): assert 1+1 == 2 def test_mul(): assert 2*3 == 6
从示例代码可以看出,unittest需要继承TestCase类,并通过assertEqual等方法来断言,而pytest则可以直接使用assert断言。
二、测试用例的发现和执行
在测试用例的发现和执行方面,unittest需要明确指定测试用例的路径和模式,而pytest会自动发现项目中的测试用例。unittest需要执行unittest.main方法来启动测试,而pytest则可以直接使用pytest命令执行。
unittest示例代码:
import unittest if __name__ == '__main__': suite = unittest.defaultTestLoader.discover('test/', pattern='test_*.py') runner = unittest.TextTestRunner() runner.run(suite)
pytest示例代码:
# 直接在项目根目录执行pytest命令 pytest
三、测试用例的参数化
测试用例的参数化可以大大减少测试代码的编写量。unittest需要通过重载TestCase的setUp和tearDown方法以及使用@unittest.parameterized.parameterized装饰器实现,而pytest则提供了很方便的@pytest.mark.parametrize装饰器。
unittest示例代码:
import unittest from parameterized import parameterized class MathTest(unittest.TestCase): @parameterized.expand([(1, 1, 2), (2, 3, 5)]) def test_add(self, a, b, c): self.assertEqual(a+b, c) if __name__ == '__main__': unittest.main()
pytest示例代码:
import pytest @pytest.mark.parametrize('a, b, c', [(1, 1, 2), (2, 3, 5)]) def test_add(a, b, c): assert a + b == c
四、插件的支持
pytest非常注重插件的可扩展性,提供了丰富的插件支持,例如自动生成测试报告、Django插件、覆盖率插件等等。而unittest则需要手动集成第三方库或者自己编写插件来支持这些功能。
pytest示例代码:
# 安装pytest-html插件 pip install pytest-html # 生成测试报告 pytest --html=report.html
五、总结
unittest和pytest在设计理念、测试用例的发现和执行、测试用例的参数化以及插件的支持等方面都有很大的不同。unittest使用传统的面向对象编程模式,需要继承TestCase类并通过assertEqual等方法进行断言,同时测试用例的执行需要明确指定路径和模式。而pytest则致力于提供简单易用的API和插件,测试函数不需要继承某个类或者调用某个框架,同时也可以自动发现测试用例并且支持丰富的插件。