page contents

Python单元测试:10个单元测试框架的使用方法!

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

attachments-2024-10-oOCGOA1b67076db3e2888.png

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

1. unittest 模块

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

基本用法:

import unittest


class TestStringMethods(unittest.TestCase):

    def test_upper(self):

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


    def test_isupper(self):

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

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


if __name__ == '__main__':

    unittest.main()

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

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

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

进阶用法:

import unittest


class TestStringMethods(unittest.TestCase):

    @classmethod

    def setUpClass(cls):

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


    def setUp(self):

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

        self.test_string = "hello world"


    def test_upper(self):

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


    def test_isupper(self):

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

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


    def tearDown(self):

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

        del self.test_string


    @classmethod

    def tearDownClass(cls):

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


if __name__ == '__main__':

    unittest.main()

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

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

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

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

2. pytest 框架

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

基本用法:

def test_upper():

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


def test_isupper():

    assert 'FOO'.isupper()

    assert not 'Foo'.isupper()

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

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

进阶用法:

import pytest


@pytest.fixture

def setup_data():

    print("setup data")

    return "hello world"


def test_upper(setup_data):

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


def test_isupper():

    assert 'HELLO'.isupper()

    assert not 'Hello'.isupper()


def test_fixture_teardown(setup_data):

    print("teardown data")

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

setup_data 函数会在 test_upper 和 test_fixture_teardown 方法之前执行。
3. Pytest-cov
pytest-cov 是一个用于生成代码覆盖率报告的插件,它可以与 pytest 配合使用。
安装:
pip install pytest-cov
基本用法:
def add(a, b):
    return a + b

def test_add():
    assert add(1, 2) == 3

def test_add_negative():
    assert add(-1, -1) == -2
定义一个简单的 add 函数和两个测试用例。
运行测试并生成覆盖率报告:
pytest --cov=my_module
--cov=my_module 参数指定要生成覆盖率报告的模块。
输出示例:
============================= test session starts ==============================
platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0
rootdir: /path/to/your/project
plugins: cov-3.0.0
collected 2 items

tests/test_my_module.py ..                                                [100%]

----------- coverage: platform darwin, python 3.10.7-final-0 -----------
Name              Stmts   Miss  Cover   Missing
-------------------------------------------------
my_module.py          1      0   100%
-------------------------------------------------
TOTAL                 1      0   100%
4. Nose2
nose2 是 nose 的改进版,它支持更多的测试发现机制和插件。
安装:
pip install nose2
基本用法:
import unittest

class TestAdd(unittest.TestCase):
    def test_add_positive(self):
        self.assertEqual(add(1, 2), 3)

    def test_add_negative(self):
        self.assertEqual(add(-1, -1), -2)
定义一个测试类 TestAdd。
运行测试:
nose2
输出示例:
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
5. Hypothesis
hypothesis 是一个强大的参数化测试库,可以生成大量随机数据进行测试。
安装:
pip install hypothesis
基本用法:
from hypothesis import given, strategies as st
from my_module import add

@given(st.integers(), st.integers())
def test_add(a, b):
    assert add(a, b) == a + b
使用 @given 装饰器定义测试函数。
st.integers() 生成整数类型的随机数据。
运行测试:
pytest
输出示例:
============================= test session starts ==============================
platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0
rootdir: /path/to/your/project
plugins: hypothesis-6.44.0
collected 1 item

tests/test_my_module.py .                                               [100%]

============================== short test summary info ===============================
hypothesis passed 100 tests for test_add, 1.00% of examples were new[100%]
6. Doctest
doctest 是 Python 标准库中的一个模块,可以将文档字符串中的示例作为测试用例。
基本用法:
def add(a, b):
    """
    >>> add(1, 2)
    3
    >>> add(-1, -1)
    -2
    """
    return a + b
在文档字符串中编写测试用例。
运行测试:
python -m doctest my_module.py
输出示例:
Trying:
    add(1, 2)
Expecting:
    3
ok
Trying:
    add(-1, -1)
Expecting:
    -2
ok
2 items had no tests:
    my_module
    my_module.add
1 items passed all tests:
   2 tests in my_module.add
2 tests in 1 items.
2 passed and 0 failed.
Test passed.
7. Pytest-Check
pytest-check 是 pytest 的一个插件,提供了一些方便的断言函数。
安装:
pip install pytest-check
基本用法:
from check import check

def test_add():
    check.equal(add(1, 2), 3)
    check.equal(add(-1, -1), -2)
使用 check.equal 断言函数进行验证。
运行测试:
pytest
输出示例:
============================= test session starts ==============================
platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0
rootdir: /path/to/your/project
plugins: check-0.2.0
collected 1 item

tests/test_my_module.py .                                               [100%]

============================== short test summary info ===============================
1 passed in 0.01s
8. Pytest-Mock
pytest-mock 是一个 pytest 插件,用于模拟对象的行为。
安装:
pip install pytest-mock
基本用法:
from my_module import some_function
import pytest

def test_some_function(mocker):
    mocker.patch('my_module.some_function', return_value=42)
    result = some_function()
    assert result == 42
使用 mocker.patch 模拟 some_function 的返回值。
运行测试:
pytest
输出示例:
============================= test session starts ==============================
platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0
rootdir: /path/to/your/project
plugins: mock-3.7.0
collected 1 item

tests/test_my_module.py .                                               [100%]

============================== short test summary info ===============================
1 passed in 0.01s
实战案例:在线购物车系统
假设我们有一个在线购物车系统,用户可以添加商品到购物车,并查看总价。我们需要编写单元测试来确保系统的正确性。
代码实现:
# shopping_cart.py

class ShoppingCart:
    def __init__(self):
        self.items = []

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

    def get_total(self):
        total = 0
        for item in self.items:
            total += item[1] * item[2]
        return total
单元测试:
# test_shopping_cart.py

import pytest
from shopping_cart import ShoppingCart

def test_add_item():
    cart = ShoppingCart()
    cart.add_item("apple", 2.0, 2)
    assert len(cart.items) == 1

def test_get_total():
    cart = ShoppingCart()
    cart.add_item("apple", 2.0, 2)
    cart.add_item("banana", 1.5, 3)
    assert cart.get_total() == 2 * 2.0 + 3 * 1.5
运行测试:
pytest
输出示例:
============================= test session starts ==============================
platform darwin -- Python 3.10.7, pytest-7.1.2, py-1.11.0, pluggy-1.0.0
rootdir: /path/to/your/project
collected 2 items

test_shopping_cart.py ..                                               [100%]

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

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

  • 发表于 2024-10-10 14:01
  • 阅读 ( 43 )
  • 分类:Python开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
小柒
小柒

1470 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章