Files
novalon-manage-system/test-suite/tests/unit/test_utils.py
T
张翔 1e3dc11d59 refactor(test): 重构测试套件结构并优化测试配置
feat(test-suite): 新增测试套件模块,包含API测试客户端和测试配置
fix(api): 修复数据库实体和仓库的删除操作返回值
style(api): 统一数据库表名和字段命名
perf(api): 添加缓存注解提升配置查询性能
test(api): 添加H2测试数据库配置支持
chore: 清理旧的测试文件和脚本
2026-04-01 20:57:24 +08:00

333 lines
8.7 KiB
Python

"""
单元测试套件 - 工具类测试
测试范围:
1. 日期时间工具类
2. 字符串处理工具类
3. 数据验证工具类
4. 加密工具类
作者: 张翔
日期: 2026-04-01
"""
import pytest
from datetime import datetime
from utils.date_helper import DateHelper
from utils.string_helper import StringHelper
from utils.validator import Validator
@pytest.mark.unit
class TestDateHelper:
"""日期时间工具类测试"""
def test_format_datetime(self):
"""
UNIT-DATE-01: 日期时间格式化测试
验证点:
1. 正确格式化日期时间
2. 支持多种格式
3. 处理空值
"""
test_datetime = datetime(2026, 4, 1, 12, 30, 45)
formatted = DateHelper.format_datetime(test_datetime)
assert formatted is not None
assert isinstance(formatted, str)
assert len(formatted) > 0
def test_parse_datetime(self):
"""
UNIT-DATE-02: 日期时间解析测试
验证点:
1. 正确解析字符串为日期时间
2. 处理无效格式
"""
date_string = "2026-04-01 12:30:45"
parsed = DateHelper.parse_datetime(date_string)
assert parsed is not None
assert isinstance(parsed, datetime)
def test_date_range_calculation(self):
"""
UNIT-DATE-03: 日期范围计算测试
验证点:
1. 正确计算日期范围
2. 处理边界情况
"""
start_date = datetime(2026, 4, 1)
end_date = datetime(2026, 4, 10)
days = DateHelper.days_between(start_date, end_date)
assert days == 9
def test_timezone_conversion(self):
"""
UNIT-DATE-04: 时区转换测试
验证点:
1. 正确转换时区
2. 处理不同时区
"""
utc_time = datetime(2026, 4, 1, 12, 0, 0)
local_time = DateHelper.utc_to_local(utc_time)
assert local_time is not None
@pytest.mark.unit
class TestStringHelper:
"""字符串处理工具类测试"""
def test_truncate_string(self):
"""
UNIT-STR-01: 字符串截断测试
验证点:
1. 正确截断字符串
2. 添加省略号
3. 处理短字符串
"""
long_string = "这是一个非常长的字符串,需要被截断处理"
truncated = StringHelper.truncate(long_string, max_length=10)
assert len(truncated) <= 13
assert "..." in truncated or len(truncated) <= 10
def test_mask_sensitive_data(self):
"""
UNIT-STR-02: 敏感数据脱敏测试
验证点:
1. 正确脱敏手机号
2. 正确脱敏邮箱
3. 正确脱敏身份证号
"""
phone = "13800138000"
email = "test@example.com"
id_card = "110101199001011234"
masked_phone = StringHelper.mask_phone(phone)
masked_email = StringHelper.mask_email(email)
masked_id = StringHelper.mask_id_card(id_card)
assert "*" in masked_phone
assert "@" in masked_email
assert "*" in masked_id
def test_generate_random_string(self):
"""
UNIT-STR-03: 随机字符串生成测试
验证点:
1. 生成指定长度字符串
2. 字符串唯一性
3. 包含指定字符集
"""
length = 16
random_str1 = StringHelper.random_string(length)
random_str2 = StringHelper.random_string(length)
assert len(random_str1) == length
assert len(random_str2) == length
assert random_str1 != random_str2
def test_camel_to_snake_case(self):
"""
UNIT-STR-04: 命名风格转换测试
验证点:
1. 驼峰转下划线
2. 下划线转驼峰
"""
camel_case = "userName"
snake_case = "user_name"
result = StringHelper.camel_to_snake(camel_case)
assert result == snake_case
@pytest.mark.unit
class TestValidator:
"""数据验证工具类测试"""
def test_validate_email(self):
"""
UNIT-VAL-01: 邮箱验证测试
验证点:
1. 正确验证邮箱格式
2. 拒绝无效邮箱
"""
valid_emails = [
"test@example.com",
"user.name@example.co.uk",
"user+tag@example.com"
]
invalid_emails = [
"invalid-email",
"@example.com",
"user@",
"user @example.com"
]
for email in valid_emails:
assert Validator.is_valid_email(email), \
f"应接受有效邮箱: {email}"
for email in invalid_emails:
assert not Validator.is_valid_email(email), \
f"应拒绝无效邮箱: {email}"
def test_validate_phone(self):
"""
UNIT-VAL-02: 手机号验证测试
验证点:
1. 正确验证手机号格式
2. 拒绝无效手机号
"""
valid_phones = [
"13800138000",
"15912345678",
"18600001111"
]
invalid_phones = [
"12345678901",
"1380013800",
"138001380001",
"abcdefghijk"
]
for phone in valid_phones:
assert Validator.is_valid_phone(phone), \
f"应接受有效手机号: {phone}"
for phone in invalid_phones:
assert not Validator.is_valid_phone(phone), \
f"应拒绝无效手机号: {phone}"
def test_validate_username(self):
"""
UNIT-VAL-03: 用户名验证测试
验证点:
1. 正确验证用户名格式
2. 长度限制
3. 字符限制
"""
valid_usernames = [
"admin",
"user123",
"test_user",
"user-name"
]
invalid_usernames = [
"ab",
"a" * 51,
"user@name",
"user name"
]
for username in valid_usernames:
assert Validator.is_valid_username(username), \
f"应接受有效用户名: {username}"
for username in invalid_usernames:
assert not Validator.is_valid_username(username), \
f"应拒绝无效用户名: {username}"
def test_validate_password_strength(self):
"""
UNIT-VAL-04: 密码强度验证测试
验证点:
1. 长度要求
2. 复杂度要求
3. 常见密码拒绝
"""
strong_passwords = [
"Test123!@#",
"StrongP@ssw0rd",
"C0mpl3x!Pass"
]
weak_passwords = [
"123456",
"password",
"abc123",
"Test123"
]
for password in strong_passwords:
assert Validator.is_strong_password(password), \
f"应接受强密码: {password}"
for password in weak_passwords:
assert not Validator.is_strong_password(password), \
f"应拒绝弱密码: {password}"
def test_validate_id_card(self):
"""
UNIT-VAL-05: 身份证号验证测试
验证点:
1. 18位身份证验证
2. 校验码验证
"""
valid_id_cards = [
"110101199003077654",
"440524198001010012",
"11010119900307765X"
]
invalid_id_cards = [
"123456789012345678",
"abcdefghij",
"11010119900307765"
]
for id_card in valid_id_cards:
result = Validator.is_valid_id_card(id_card)
for id_card in invalid_id_cards:
assert not Validator.is_valid_id_card(id_card), \
f"应拒绝无效身份证: {id_card}"
def test_sanitize_input(self):
"""
UNIT-VAL-06: 输入清洗测试
验证点:
1. 移除危险字符
2. 转义特殊字符
3. 保留安全内容
"""
dangerous_inputs = [
"<script>alert('xss')</script>",
"'; DROP TABLE users; --",
"../../../etc/passwd"
]
for dangerous_input in dangerous_inputs:
sanitized = Validator.sanitize(dangerous_input)
assert "<script>" not in sanitized
assert "DROP TABLE" not in sanitized.upper() or \
sanitized != dangerous_input