文章目录
-
- unnittest
-
- [1. 基本结构](#1. 基本结构)
- [2. 常用断言方法](#2. 常用断言方法)
- [3. 测试生命周期方法](#3. 测试生命周期方法)
- [4. 跳过测试](#4. 跳过测试)
- [5. 运行测试](#5. 运行测试)
- pytest
-
- [1. 基本测试用法](#1. 基本测试用法)
- [2. 安装 `pytest`](#2. 安装
pytest
) - [3. 运行测试](#3. 运行测试)
- [4. 使用 `assert` 断言](#4. 使用
assert
断言) - [5. 异常测试](#5. 异常测试)
- [6. 参数化测试](#6. 参数化测试)
- [7. 测试前后设置](#7. 测试前后设置)
- [8. 跳过测试和标记失败](#8. 跳过测试和标记失败)
- [9. 测试夹具 (Fixtures)](#9. 测试夹具 (Fixtures))
- [10. 生成测试报告](#10. 生成测试报告)
- [11. 插件](#11. 插件)
- [12. 运行整个目录中的测试](#12. 运行整个目录中的测试)
unnittest
unittest
是 Python 自带的单元测试框架,用于编写、组织和运行测试。下面是一些常见的 unittest
用法:
1. 基本结构
在 unittest
中,通常通过创建类继承自 unittest.TestCase
来定义测试用例,并在该类中编写测试方法。测试方法的名称必须以 test_
开头。
python
import unittest
# 定义要测试的函数
def add(x, y):
return x + y
# 定义测试类
class TestMath(unittest.TestCase):
# 编写测试方法
def test_add(self):
self.assertEqual(add(1, 2), 3) # 测试 1 + 2 是否等于 3
self.assertEqual(add(-1, 1), 0) # 测试 -1 + 1 是否等于 0
# 运行测试
if __name__ == '__main__':
unittest.main()
2. 常用断言方法
unittest.TestCase
提供了一些常见的断言方法来检查代码的行为:
assertEqual(a, b)
: 检查a == b
assertNotEqual(a, b)
: 检查a != b
assertTrue(x)
: 检查x
是否为True
assertFalse(x)
: 检查x
是否为False
assertIs(a, b)
: 检查a is b
assertIsNot(a, b)
: 检查a is not b
assertIsNone(x)
: 检查x
是否为None
assertIsNotNone(x)
: 检查x
是否不为None
assertIn(a, b)
: 检查a
是否在b
中assertNotIn(a, b)
: 检查a
是否不在b
中assertRaises(exc, callable, *args, **kwds)
: 检查是否抛出异常
3. 测试生命周期方法
unittest
提供了一些方法来管理测试前后的操作:
setUp()
: 每个测试方法执行前调用tearDown()
: 每个测试方法执行后调用setUpClass()
: 在所有测试开始之前调用(类方法,使用@classmethod
修饰)tearDownClass()
: 在所有测试结束之后调用(类方法,使用@classmethod
修饰)
python
class TestMath(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("所有测试之前调用")
def setUp(self):
print("每个测试之前调用")
def test_add(self):
self.assertEqual(add(1, 2), 3)
def tearDown(self):
print("每个测试之后调用")
@classmethod
def tearDownClass(cls):
print("所有测试之后调用")
4. 跳过测试
有时某些测试可能需要跳过或被标记为待定,unittest
提供了几种方式来实现:
@unittest.skip(reason)
: 跳过测试@unittest.skipIf(condition, reason)
: 条件为真时跳过@unittest.skipUnless(condition, reason)
: 条件为假时跳过@unittest.expectedFailure
: 预期会失败的测试
python
class TestMath(unittest.TestCase):
@unittest.skip("跳过此测试")
def test_add(self):
self.assertEqual(add(1, 2), 3)
@unittest.skipIf(1 < 2, "条件为真时跳过")
def test_subtract(self):
self.assertEqual(subtract(2, 1), 1)
5. 运行测试
可以直接通过命令行运行测试文件:
bash
python -m unittest test_module.py
也可以一次性运行整个目录的测试:
bash
python -m unittest discover
以上是 Python 中 unittest
框架的常见用法,你可以根据需要编写单元测试并运行以确保代码的正确性。
pytest
pytest
是 Python 中非常流行的测试框架,简单易用,功能强大,适合编写单元测试和集成测试。相比于 unittest
,pytest
具有更简洁的语法和更丰富的插件生态。
1. 基本测试用法
pytest
可以直接通过函数来编写测试,而不需要像 unittest
那样定义测试类。测试函数的名称必须以 test_
开头。
python
# test_example.py
def add(x, y):
return x + y
# 编写测试函数
def test_add():
assert add(1, 2) == 3
assert add(-1, 1) == 0
2. 安装 pytest
bash
pip install pytest
3. 运行测试
直接在命令行中运行 pytest
命令,它会自动发现所有以 test_
开头的文件和函数:
bash
pytest
还可以指定某个具体的测试文件或测试函数:
bash
pytest test_example.py
pytest test_example.py::test_add
4. 使用 assert
断言
pytest
直接使用 Python 的 assert
语句进行断言,而不需要使用 unittest
中复杂的断言方法。当断言失败时,pytest
会给出详细的错误报告。
python
def test_add():
assert add(1, 2) == 3
assert add(-1, 1) == 0
assert add(0, 0) == 0
5. 异常测试
pytest
提供了 pytest.raises
来检查代码是否抛出指定的异常。
python
import pytest
def divide(x, y):
if y == 0:
raise ValueError("除数不能为零")
return x / y
def test_divide():
with pytest.raises(ValueError, match="除数不能为零"):
divide(1, 0)
6. 参数化测试
通过 pytest.mark.parametrize
装饰器,可以实现参数化测试,让同一个测试函数可以测试多个输入和预期输出。
python
import pytest
# 参数化测试
@pytest.mark.parametrize("x, y, expected", [
(1, 2, 3),
(-1, 1, 0),
(0, 0, 0),
])
def test_add(x, y, expected):
assert add(x, y) == expected
7. 测试前后设置
pytest
提供了 setup_function
和 teardown_function
用于在每个测试函数运行前后执行一些准备或清理工作,类似于 unittest
中的 setUp
和 tearDown
。
python
def setup_function():
print("每个测试之前执行")
def teardown_function():
print("每个测试之后执行")
def test_example():
assert 1 == 1
8. 跳过测试和标记失败
pytest
支持条件跳过测试以及标记测试为预期失败:
@pytest.mark.skip(reason="跳过原因")
:跳过某个测试@pytest.mark.skipif(condition, reason="跳过原因")
:条件为真时跳过@pytest.mark.xfail
:标记为预期失败的测试
python
import pytest
@pytest.mark.skip(reason="暂时跳过")
def test_skip():
assert 1 == 1
@pytest.mark.skipif(1 < 2, reason="条件为真时跳过")
def test_skipif():
assert 1 == 1
@pytest.mark.xfail
def test_xfail():
assert 1 == 2 # 预期失败
9. 测试夹具 (Fixtures)
pytest
提供了强大的夹具功能(Fixture)来在测试中共享和复用资源。通过使用 @pytest.fixture
装饰器可以定义一个夹具,并在测试函数中传入它。
python
import pytest
@pytest.fixture
def sample_data():
return {"name": "Alice", "age": 30}
def test_sample_data(sample_data):
assert sample_data["name"] == "Alice"
assert sample_data["age"] == 30
10. 生成测试报告
运行 pytest
时可以生成更详细的报告:
bash
pytest -v # 显示每个测试的详细信息
pytest --maxfail=3 -v # 最多失败3个测试后停止
pytest --tb=short # 输出简短的回溯信息
11. 插件
pytest
具有丰富的插件生态系统。例如:
pytest-cov
: 用于生成代码覆盖率报告pytest-xdist
: 并行运行测试pytest-mock
: 与unittest.mock
集成的插件
安装插件的方式:
bash
pip install pytest-cov
pytest --cov=your_module test_example.py # 运行并生成覆盖率报告
12. 运行整个目录中的测试
pytest
可以一次运行整个目录中的测试文件,自动查找所有 test_
开头的文件和测试函数:
bash
pytest tests/
pytest
的语法简单而灵活,非常适合写 Python 的测试代码。希望这些用法对你有帮助!