本文目录导读:
我来介绍几种Python批量测试案例的编写方法:
使用unittest框架
import unittest
import math
# 批量测试数学函数
class TestMathFunctions(unittest.TestCase):
def test_power(self):
"""批量测试乘方运算"""
test_cases = [
(2, 3, 8),
(3, 2, 9),
(10, 0, 1),
(2, -1, 0.5),
(5, 2, 25)
]
for base, exp, expected in test_cases:
with self.subTest(f"测试 {base}^{exp}"):
result = pow(base, exp)
self.assertEqual(result, expected)
def test_sqrt(self):
"""批量测试平方根"""
test_cases = [
(4, 2),
(9, 3),
(16, 4),
(25, 5),
(100, 10)
]
for number, expected in test_cases:
with self.subTest(f"sqrt({number})"):
result = math.sqrt(number)
self.assertAlmostEqual(result, expected)
# 批量测试字符串处理
class TestStringMethods(unittest.TestCase):
def test_string_operations(self):
"""批量测试字符串操作"""
test_data = [
# (input_string, expected_length, expected_upper)
("hello", 5, "HELLO"),
("Python", 6, "PYTHON"),
("test123", 7, "TEST123"),
("", 0, ""),
("ABC", 3, "ABC")
]
for input_str, exp_len, exp_upper in test_data:
with self.subTest(f"测试: '{input_str}'"):
self.assertEqual(len(input_str), exp_len)
self.assertEqual(input_str.upper(), exp_upper)
# 批量测试数据处理
class TestDataProcessing(unittest.TestCase):
def test_calculate_average(self):
"""批量测试平均值计算"""
test_cases = [
([1, 2, 3, 4, 5], 3),
([10, 20, 30], 20),
([0, 0, 0], 0),
([5], 5),
([1, 2, 3, 4], 2.5)
]
for numbers, expected_avg in test_cases:
with self.subTest(f"平均值: {numbers}"):
avg = sum(numbers) / len(numbers) if numbers else 0
self.assertAlmostEqual(avg, expected_avg)
if __name__ == '__main__':
unittest.main()
使用参数化测试(第三方库)
pip install parameterized
from parameterized import parameterized
import unittest
class TestParameterized(unittest.TestCase):
@parameterized.expand([
("case1", 2, 3, 6),
("case2", 0, 5, 0),
("case3", -2, 3, -6),
("case4", 2.5, 2, 5.0),
("case5", 10, 0, 0),
])
def test_multiply(self, name, a, b, expected):
"""参数化乘法测试"""
result = a * b
self.assertEqual(result, expected)
@parameterized.expand([
("valid", "user@example.com", True),
("invalid_no_at", "userexample.com", False),
("invalid_dot", "user@com", False),
("empty", "", False),
("valid_complex", "user.name+tag@example.co.uk", True),
])
def test_email_validation(self, name, email, expected_valid):
"""参数化邮箱验证测试"""
import re
pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'
result = bool(re.match(pattern, email))
self.assertEqual(result, expected_valid)
if __name__ == '__main__':
unittest.main()
使用pytest框架(推荐)
import pytest
import json
# 测试数据
test_data = [
(1, 2, 3),
(5, 5, 10),
(-1, 1, 0),
(0, 0, 0),
(100, 200, 300)
]
# 简单的参数化测试
@pytest.mark.parametrize("a,b,expected", test_data)
def test_addition(a, b, expected):
"""批量测试加法"""
result = a + b
assert result == expected
# 测试用户数据处理
class TestUserData:
@pytest.mark.parametrize("user_data,expected_valid", [
({"name": "张三", "age": 25, "email": "zhang@test.com"}, True),
({"name": "", "age": 25, "email": "test@test.com"}, False),
({"name": "李四", "age": -1, "email": "li@test.com"}, False),
({"name": "王五", "age": 150, "email": "wang@test.com"}, False),
({"name": "赵六", "age": 30, "email": ""}, False),
])
def test_user_validation(self, user_data, expected_valid):
"""批量测试用户数据验证"""
def validate_user(data):
if not data.get("name"):
return False
if not (0 < data.get("age", 0) < 120):
return False
if not data.get("email"):
return False
return True
result = validate_user(user_data)
assert result == expected_valid
# 从文件读取测试数据
def load_test_data():
"""从JSON文件加载测试数据"""
data = [
{"input": "hello", "expected": "HELLO"},
{"input": "world", "expected": "WORLD"},
{"input": "python", "expected": "PYTHON"},
{"input": "test", "expected": "TEST"},
]
return [(d["input"], d["expected"]) for d in data]
@pytest.mark.parametrize("input_str,expected", load_test_data())
def test_uppercase_from_data(input_str, expected):
"""从数据源加载测试数据"""
result = input_str.upper()
assert result == expected
# 组合参数化测试
@pytest.mark.parametrize("operation", ["add", "subtract", "multiply"])
@pytest.mark.parametrize("a,b", [(2, 3), (5, 5), (10, 0)])
def test_operations(operation, a, b):
"""组合参数化测试"""
if operation == "add":
result = a + b
elif operation == "subtract":
result = a - b
elif operation == "multiply":
result = a * b
# 验证基本运算
assert isinstance(result, (int, float))
完整的批量测试示例
import unittest
import pytest
from typing import List, Tuple
# 要测试的业务函数
def calculate_discount(price: float, quantity: int) -> float:
"""计算折扣价格"""
if price < 0 or quantity < 0:
raise ValueError("价格和数量不能为负数")
total = price * quantity
# 批量折扣
if quantity >= 100:
total *= 0.8 # 20% off
elif quantity >= 50:
total *= 0.9 # 10% off
elif quantity >= 10:
total *= 0.95 # 5% off
return round(total, 2)
class TestDiscountCalculation:
# 测试数据: (价格, 数量, 期望折扣价)
test_cases = [
(100, 1, 100.0), # 无折扣
(100, 10, 950.0), # 5%折扣
(100, 50, 4500.0), # 10%折扣
(100, 100, 8000.0), # 20%折扣
(50, 5, 250.0), # 无折扣
(20, 200, 3200.0), # 20%折扣
(1000, 1, 1000.0), # 高价单品
(0.99, 100, 79.2), # 低价批量
]
@pytest.mark.parametrize("price,quantity,expected", test_cases)
def test_discount_cases(self, price, quantity, expected):
"""批量测试折扣计算"""
result = calculate_discount(price, quantity)
assert result == expected, f"价格{price}*数量{quantity}应得{expected},实际{result}"
@pytest.mark.parametrize("price,quantity", [
(-100, 10),
(100, -5),
(-1, -1)
])
def test_invalid_input(self, price, quantity):
"""测试无效输入"""
with pytest.raises(ValueError):
calculate_discount(price, quantity)
# 批量测试报告生成
def generate_test_report(results: List[Tuple[str, bool, str]]):
"""生成测试报告"""
print("\n" + "="*50)
print("测试报告")
print("="*50)
passed = 0
failed = 0
for test_name, result, error_msg in results:
status = "✓" if result else "✗"
print(f"{status} {test_name}: {'通过' if result else f'失败 - {error_msg}'}")
if result:
passed += 1
else:
failed += 1
print("="*50)
print(f"总计: {len(results)} | 通过: {passed} | 失败: {failed}")
print("="*50)
# 主函数
if __name__ == "__main__":
# 使用unittest运行
print("使用unittest运行:")
unittest.main(argv=[''], exit=False)
# 使用pytest运行
print("\n\n使用pytest运行:")
pytest.main(['-v', __file__])
# 自定义测试运行
print("\n\n自定义测试批量运行:")
test_runner = TestDiscountCalculation()
test_results = []
for price, quantity, expected in TestDiscountCalculation.test_cases:
try:
test_runner.test_discount_cases(price, quantity, expected)
test_results.append((f"折扣测试({price},{quantity})", True, ""))
except AssertionError as e:
test_results.append((f"折扣测试({price},{quantity})", False, str(e)))
generate_test_report(test_results)
使用建议
- 对于小型项目:使用
unittest即可 - 对于中型项目:推荐
pytest,更简洁灵活 - 需要大量重复测试:使用
parameterized或@pytest.mark.parametrize - 测试数据复杂:从外部文件(JSON/CSV/Excel)读取测试数据
- 测试组织:按功能模块分组,每个测试类的测试用例保持相关
运行方式
# 运行unittest python -m unittest test_file.py # 运行pytest(更详细输出) pytest -v test_file.py # 运行特定测试类 pytest -v test_file.py::TestDiscountCalculation
这些方法可以让你高效地编写和管理批量测试案例,提高测试覆盖率和代码质量。
标签: Pytest