单元测试软件开发中不可或缺的一部分,它能够帮助开发者确保代码的质量和稳定性。Python 社区提供了多种单元测试框架,每种框架都有其独特的优势和适用场景。本文将介绍几种常见的 Python 单元测试框架,并通过实际例子帮助读者更好地理解和使用它们。

1. unittest 模块

unittest 是 Python 自带的标准库之一,它基于 Java 的 JUnit 框架设计,提供了一套完整的单元测试框架。

基本用法:

  1.  import unittest

  2.   class TestStringMethods(unittest.TestCase):

  3.    def test_upper(self):

  4.    self.assertEqual('foo'.upper(), 'FOO')

  5.    def test_isupper(self):

  6.    self.assertTrue('FOO'.isupper())

  7.    self.assertFalse('Foo'.isupper())

  8.   if __name__ == '__main__':

  9.    unittest.main()

·这段代码定义了一个测试类 TestStringMethods,继承自 unittest.TestCase。

· test_upper 和 test_isupper 方法分别测试字符串的大写转换和是否全为大写的检查。

· unittest.main() 启动测试运行器。

进阶用法:

  1.  import unittest

  2.   class TestStringMethods(unittest.TestCase):

  3.    @classmethod

  4.    def setUpClass(cls):

  5.    print("这个方法只在所有测试开始前执行一次")

  6.    def setUp(self):

  7.    print("这个方法会在每个测试方法之前执行")

  8.    self.test_string = "hello world"

  9.    def test_upper(self):

  10.    self.assertEqual(self.test_string.upper(), 'HELLO WORLD')

  11.    def test_isupper(self):

  12.    self.assertTrue('HELLO'.isupper())

  13.    self.assertFalse('Hello'.isupper())

  14.    def tearDown(self):

  15.    print("这个方法会在每个测试方法之后执行")

  16.    del self.test_string

  17.    @classmethod

  18.    def tearDownClass(cls):

  19.    print("这个方法在所有测试结束后执行一次")

  20.   if __name__ == '__main__':

  21.    unittest.main()

 ·setUpClass 类方法在整个测试类开始前执行一次。

  · setUp 方法在每个测试方法前执行,用于准备测试数据。

  · tearDown 方法在每个测试方法后执行,用于清理测试环境。

  · tearDownClass 类方法在所有测试结束后执行一次。

  2. pytest 框架

  pytest 是目前非常流行的一个第三方单元测试框架,它简洁易用,扩展性强。

  基本用法:

  1.  def test_upper():

  2.    assert 'foo'.upper() == 'FOO'

  3.   def test_isupper():

  4.    assert 'FOO'.isupper()

  5.    assert not 'Foo'.isupper()

 ·使用 assert 断言来验证期望的结果。

  · 直接定义函数名以 test_ 开头的方法作为测试用例

  进阶用法:

  1.  import pytest

  2.   @pytest.fixture

  3.   def setup_data():

  4.    print("setup data")

  5.    return "hello world"

  6.   def test_upper(setup_data):

  7.    assert setup_data.upper() == "HELLO WORLD"

  8.   def test_isupper():

  9.    assert 'HELLO'.isupper()

  10.    assert not 'Hello'.isupper()

  11.   def test_fixture_teardown(setup_data):

  12.    print("teardown data")

 ·@pytest.fixture 装饰器定义了一个测试夹具(fixture),可以在多个测试用例之间共享数据。

  · setup_data 函数会在 test_upper 和 test_fixture_teardown 方法之前执行。

  3. Pytest-cov

  pytest-cov 是一个用于生成代码覆盖率报告的插件,它可以与 pytest 配合使用。

  安装:

  pip install pytest-cov

 基本用法:

  1.  def add(a, b):

  2.    return a + b

  3.   def test_add():

  4.    assert add(1, 2) == 3

  5.   def test_add_negative():

  6.    assert add(-1, -1) == -2

定义一个简单的 add 函数和两个测试用例。

  运行测试并生成覆盖率报告:

 pytest --cov=my_module

 --cov=my_module 参数指定要生成覆盖率报告的模块。

  输出示例:


  1. ============================= test session starts ==============================

  2.   platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0

  3.   rootdir: /path/to/your/project

  4.   plugins: cov-3.0.0

  5.   collected 2 items

  6.   tests/test_my_module.py .. [100%]

  7.   ----------- coverage: platform darwin, python 3.10.7-final-0 -----------

  8.   Name Stmts Miss Cover Missing

  9.   -------------------------------------------------

  10.   my_module.py 1 0 100%

  11.   -------------------------------------------------

  12.   TOTAL 1 0 100%

4. Nose2

  nose2 是 nose 的改进版,它支持更多的测试发现机制和插件。

  安装:

pip install nose2

基本用法:


  1.  import unittest

  2.   class TestAdd(unittest.TestCase):

  3.    def test_add_positive(self):

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

  5.    def test_add_negative(self):

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

 定义一个测试类 TestAdd。

  运行测试:

  nose2

 输出示例:


  1.   .

  2.   ----------------------------------------------------------------------

  3.   Ran 1 test in 0.001s

  4.   OK

5. Hypothesis

  hypothesis 是一个强大的参数化测试库,可以生成大量随机数据进行测试。

  安装:

 pip install hypothesis

基本用法:


  1.  from hypothesis import given, strategies as st

  2.   from my_module import add

  3.   @given(st.integers(), st.integers())

  4.   def test_add(a, b):

  5.    assert add(a, b) == a + b

 ·使用 @given 装饰器定义测试函数。

  · st.integers() 生成整数类型的随机数据。

  运行测试:

  pytest

输出示例:


  1. ============================= test session starts ==============================

  2.   platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0

  3.   rootdir: /path/to/your/project

  4.   plugins: hypothesis-6.44.0

  5.   collected 1 item

  6.   tests/test_my_module.py . [100%]

  7.   ============================== short test summary info ===============================

  8.   hypothesis passed 100 tests for test_add, 1.00% of examples were new[100%]

 6. Doctest

  doctest 是 Python 标准库中的一个模块,可以将文档字符串中的示例作为测试用例。

  基本用法:


  1. def add(a, b):

  2.    """

  3.    >>> add(1, 2)

  4.    3

  5.    >>> add(-1, -1)

  6.    -2

  7.    """

  8.    return a + b

在文档字符串中编写测试用例。

  运行测试:

python -m doctest my_module.py

输出示例:


  1.  Trying:

  2.    add(1, 2)

  3.   Expecting:

  4.    3

  5.   ok

  6.   Trying:

  7.    add(-1, -1)

  8.   Expecting:

  9.    -2

  10.   ok

  11.   2 items had no tests:

  12.    my_module

  13.    my_module.add

  14.   1 items passed all tests:

  15.    2 tests in my_module.add

  16.   2 tests in 1 items.

  17.   2 passed and 0 failed.

  18.   Test passed.

7. Pytest-Check

  pytest-check 是 pytest 的一个插件,提供了一些方便的断言函数。

  安装:

pip install pytest-check

  基本用法:


  1.  from check import check

  2.   def test_add():

  3.    check.equal(add(1, 2), 3)

  4.    check.equal(add(-1, -1), -2)

使用 check.equal 断言函数进行验证。

  运行测试:

 pytest

输出示例:


  1.  ============================= test session starts ==============================

  2.   platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0

  3.   rootdir: /path/to/your/project

  4.   plugins: check-0.2.0

  5.   collected 1 item

  6.   tests/test_my_module.py . [100%]

  7.   ============================== short test summary info ===============================

  8.   1 passed in 0.01s

8. Pytest-Mock

  pytest-mock 是一个 pytest 插件,用于模拟对象的行为。

  安装:

 pip install pytest-mock

基本用法:


  1. from my_module import some_function

  2.   import pytest

  3.   def test_some_function(mocker):

  4.    mocker.patch('my_module.some_function', return_value=42)

  5.    result = some_function()

  6.    assert result == 42

使用 mocker.patch 模拟 some_function 的返回值。

  运行测试:

 pytest

  输出示例:


  1. ============================= test session starts ==============================

  2.   platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0

  3.   rootdir: /path/to/your/project

  4.   plugins: mock-3.7.0

  5.   collected 1 item

  6.   tests/test_my_module.py . [100%]

  7.   ============================== short test summary info ===============================

  8.   1 passed in 0.01s

 实战案例:在线购物车系统

  假设我们有一个在线购物车系统,用户可以添加商品到购物车,并查看总价。我们需要编写单元测试来确保系统的正确性。

  代码实现:


  1.  # shopping_cart.py

  2.   class ShoppingCart:

  3.    def __init__(self):

  4.    self.items = []

  5.    def add_item(self, item_name, price, quantity=1):

  6.    self.items.append((item_name, price, quantity))

  7.    def get_total(self):

  8.    total = 0

  9.    for item in self.items:

  10.    total += item[1] * item[2]

  11.    return total

单元测试:


  1.  # test_shopping_cart.py

  2.   import pytest

  3.   from shopping_cart import ShoppingCart

  4.   def test_add_item():

  5.    cart = ShoppingCart()

  6.    cart.add_item("apple", 2.0, 2)

  7.    assert len(cart.items) == 1

  8.   def test_get_total():

  9.    cart = ShoppingCart()

  10.    cart.add_item("apple", 2.0, 2)

  11.    cart.add_item("banana", 1.5, 3)

  12.    assert cart.get_total() == 2 * 2.0 + 3 * 1.5

 运行测试:

pytest

输出示例:


  1.  ============================= test session starts ==============================

  2.   platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0

  3.   rootdir: /path/to/your/project

  4.   collected 2 items

  5.   test_shopping_cart.py .. [100%]

  6.   ============================== short test summary info ===============================

  7.   2 passed in 0.01s

总结

本文介绍了 Python 中常用的几种单元测试框架及其基本用法,包括 unittest、pytest、pytest-cov、nose2、hypothesis、doctest、pytest-check 和 pytest-mock。通过实战案例展示了如何使用这些框架编写有效的单元测试,帮助确保代码的质量和稳定性。

感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取   

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐