unittest和pytest的区别详解

发布时间:2023-05-23

一、设计理念

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和插件,测试函数不需要继承某个类或者调用某个框架,同时也可以自动发现测试用例并且支持丰富的插件。