Re-structure the project.
This commit is contained in:
273
tests/normalize/normalizers/README.md
Normal file
273
tests/normalize/normalizers/README.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# Normalizer Tests
|
||||
|
||||
每个 normalizer 模块都有完整的测试覆盖。
|
||||
|
||||
## 测试结构
|
||||
|
||||
```
|
||||
tests/normalize/normalizers/
|
||||
├── __init__.py
|
||||
├── test_invoice_number_normalizer.py # InvoiceNumberNormalizer 测试 (12 个测试)
|
||||
├── test_ocr_normalizer.py # OCRNormalizer 测试 (9 个测试)
|
||||
├── test_bankgiro_normalizer.py # BankgiroNormalizer 测试 (11 个测试)
|
||||
├── test_plusgiro_normalizer.py # PlusgiroNormalizer 测试 (10 个测试)
|
||||
├── test_amount_normalizer.py # AmountNormalizer 测试 (15 个测试)
|
||||
├── test_date_normalizer.py # DateNormalizer 测试 (19 个测试)
|
||||
├── test_organisation_number_normalizer.py # OrganisationNumberNormalizer 测试 (11 个测试)
|
||||
├── test_supplier_accounts_normalizer.py # SupplierAccountsNormalizer 测试 (13 个测试)
|
||||
├── test_customer_number_normalizer.py # CustomerNumberNormalizer 测试 (12 个测试)
|
||||
└── README.md # 本文件
|
||||
```
|
||||
|
||||
## 运行测试
|
||||
|
||||
### 运行所有 normalizer 测试
|
||||
|
||||
```bash
|
||||
# 在 WSL 环境中
|
||||
conda activate invoice-py311
|
||||
pytest tests/normalize/normalizers/ -v
|
||||
```
|
||||
|
||||
### 运行单个 normalizer 的测试
|
||||
|
||||
```bash
|
||||
# 测试 InvoiceNumberNormalizer
|
||||
pytest tests/normalize/normalizers/test_invoice_number_normalizer.py -v
|
||||
|
||||
# 测试 AmountNormalizer
|
||||
pytest tests/normalize/normalizers/test_amount_normalizer.py -v
|
||||
|
||||
# 测试 DateNormalizer
|
||||
pytest tests/normalize/normalizers/test_date_normalizer.py -v
|
||||
```
|
||||
|
||||
### 查看测试覆盖率
|
||||
|
||||
```bash
|
||||
pytest tests/normalize/normalizers/ --cov=src/normalize/normalizers --cov-report=html
|
||||
```
|
||||
|
||||
## 测试统计
|
||||
|
||||
**总计**: 112 个测试用例
|
||||
**状态**: ✅ 全部通过
|
||||
**执行时间**: ~5.6 秒
|
||||
|
||||
### 各 Normalizer 测试数量
|
||||
|
||||
| Normalizer | 测试数量 | 覆盖率 |
|
||||
|------------|---------|-------|
|
||||
| InvoiceNumberNormalizer | 12 | 100% |
|
||||
| OCRNormalizer | 9 | 100% |
|
||||
| BankgiroNormalizer | 11 | 100% |
|
||||
| PlusgiroNormalizer | 10 | 100% |
|
||||
| AmountNormalizer | 15 | 100% |
|
||||
| DateNormalizer | 19 | 93% |
|
||||
| OrganisationNumberNormalizer | 11 | 100% |
|
||||
| SupplierAccountsNormalizer | 13 | 100% |
|
||||
| CustomerNumberNormalizer | 12 | 100% |
|
||||
|
||||
## 测试覆盖的场景
|
||||
|
||||
### 通用测试 (所有 normalizer)
|
||||
|
||||
- ✅ 空字符串处理
|
||||
- ✅ None 值处理
|
||||
- ✅ Callable 接口 (`__call__`)
|
||||
- ✅ 基本功能验证
|
||||
|
||||
### InvoiceNumberNormalizer
|
||||
|
||||
- ✅ 纯数字发票号
|
||||
- ✅ 带前缀的发票号 (INV-, etc.)
|
||||
- ✅ 字母数字混合
|
||||
- ✅ 特殊字符处理
|
||||
- ✅ Unicode 字符清理
|
||||
- ✅ 多个分隔符
|
||||
- ✅ 无数字内容
|
||||
- ✅ 重复变体去除
|
||||
|
||||
### OCRNormalizer
|
||||
|
||||
- ✅ 纯数字 OCR
|
||||
- ✅ 带前缀 (OCR:)
|
||||
- ✅ 空格分隔
|
||||
- ✅ 连字符分隔
|
||||
- ✅ 混合分隔符
|
||||
- ✅ 超长 OCR 号码
|
||||
|
||||
### BankgiroNormalizer
|
||||
|
||||
- ✅ 8 位数字 (带/不带连字符)
|
||||
- ✅ 7 位数字格式
|
||||
- ✅ 特殊连字符类型 (en-dash, etc.)
|
||||
- ✅ 空格处理
|
||||
- ✅ 前缀处理 (BG:)
|
||||
- ✅ OCR 错误变体生成
|
||||
|
||||
### PlusgiroNormalizer
|
||||
|
||||
- ✅ 8 位数字 (带/不带连字符)
|
||||
- ✅ 7 位数字
|
||||
- ✅ 9 位数字
|
||||
- ✅ 空格处理
|
||||
- ✅ 前缀处理 (PG:)
|
||||
- ✅ OCR 错误变体生成
|
||||
|
||||
### AmountNormalizer
|
||||
|
||||
- ✅ 整数金额
|
||||
- ✅ 逗号小数分隔符
|
||||
- ✅ 点小数分隔符
|
||||
- ✅ 空格千位分隔符
|
||||
- ✅ 空格作为小数分隔符 (瑞典格式)
|
||||
- ✅ 美国格式 (1,390.00)
|
||||
- ✅ 欧洲格式 (1.390,00)
|
||||
- ✅ 货币符号移除 (kr, SEK)
|
||||
- ✅ 大金额处理
|
||||
- ✅ 冒号破折号后缀 (1234:-)
|
||||
|
||||
### DateNormalizer
|
||||
|
||||
- ✅ ISO 格式 (2025-12-13)
|
||||
- ✅ 欧洲斜杠格式 (13/12/2025)
|
||||
- ✅ 欧洲点格式 (13.12.2025)
|
||||
- ✅ 紧凑格式 YYYYMMDD
|
||||
- ✅ 紧凑格式 YYMMDD
|
||||
- ✅ 短年份格式 (DD.MM.YY)
|
||||
- ✅ 瑞典月份名称 (december, dec)
|
||||
- ✅ 瑞典月份缩写
|
||||
- ✅ 带时间的 ISO 格式
|
||||
- ✅ 歧义日期双重解析
|
||||
- ✅ 中点分隔符
|
||||
- ✅ 空格格式
|
||||
- ✅ 无效日期处理
|
||||
- ✅ 2 位年份世纪判断
|
||||
|
||||
### OrganisationNumberNormalizer
|
||||
|
||||
- ✅ 带/不带连字符
|
||||
- ✅ VAT 号码提取
|
||||
- ✅ VAT 号码生成
|
||||
- ✅ 12 位带世纪组织号
|
||||
- ✅ VAT 带空格
|
||||
- ✅ 大小写混合 VAT 前缀
|
||||
- ✅ OCR 错误变体生成
|
||||
|
||||
### SupplierAccountsNormalizer
|
||||
|
||||
- ✅ 单个 Plusgiro
|
||||
- ✅ 单个 Bankgiro
|
||||
- ✅ 多账号 (| 分隔)
|
||||
- ✅ 前缀标准化
|
||||
- ✅ 前缀带空格
|
||||
- ✅ 空账号忽略
|
||||
- ✅ 无前缀账号
|
||||
- ✅ 7 位账号
|
||||
- ✅ 10 位账号
|
||||
- ✅ 混合格式账号
|
||||
|
||||
### CustomerNumberNormalizer
|
||||
|
||||
- ✅ 字母数字+空格+连字符
|
||||
- ✅ 字母数字+空格
|
||||
- ✅ 大小写变体
|
||||
- ✅ 纯数字
|
||||
- ✅ 仅连字符
|
||||
- ✅ 仅空格
|
||||
- ✅ 大写重复去除
|
||||
- ✅ 复杂客户编号
|
||||
- ✅ 瑞典客户编号格式 (UMJ 436-R)
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 使用 pytest fixtures
|
||||
|
||||
每个测试类都使用 `@pytest.fixture` 创建 normalizer 实例:
|
||||
|
||||
```python
|
||||
@pytest.fixture
|
||||
def normalizer(self):
|
||||
"""Create normalizer instance for testing"""
|
||||
return InvoiceNumberNormalizer()
|
||||
|
||||
def test_something(self, normalizer):
|
||||
result = normalizer.normalize('test')
|
||||
assert 'expected' in result
|
||||
```
|
||||
|
||||
### 2. 清晰的测试命名
|
||||
|
||||
测试方法名清楚描述测试场景:
|
||||
|
||||
```python
|
||||
def test_with_dash_8_digits(self, normalizer):
|
||||
"""8-digit Bankgiro with dash should generate variants"""
|
||||
...
|
||||
```
|
||||
|
||||
### 3. 断言具体行为
|
||||
|
||||
明确测试期望的行为:
|
||||
|
||||
```python
|
||||
result = normalizer.normalize('5393-9484')
|
||||
assert '5393-9484' in result # 保留原始格式
|
||||
assert '53939484' in result # 生成无连字符格式
|
||||
```
|
||||
|
||||
### 4. 边界条件测试
|
||||
|
||||
每个 normalizer 都测试:
|
||||
- 空字符串
|
||||
- None 值
|
||||
- 特殊字符
|
||||
- 极端值
|
||||
|
||||
### 5. 接口一致性测试
|
||||
|
||||
验证 callable 接口:
|
||||
|
||||
```python
|
||||
def test_callable_interface(self, normalizer):
|
||||
"""Normalizer should be callable via __call__"""
|
||||
result = normalizer('test-value')
|
||||
assert result is not None
|
||||
```
|
||||
|
||||
## 添加新测试
|
||||
|
||||
为新功能添加测试:
|
||||
|
||||
```python
|
||||
def test_new_feature(self, normalizer):
|
||||
"""Description of what this tests"""
|
||||
# Arrange
|
||||
input_value = 'test-input'
|
||||
|
||||
# Act
|
||||
result = normalizer.normalize(input_value)
|
||||
|
||||
# Assert
|
||||
assert 'expected-output' in result
|
||||
assert len(result) > 0
|
||||
```
|
||||
|
||||
## CI/CD 集成
|
||||
|
||||
这些测试可以轻松集成到 CI/CD 流程:
|
||||
|
||||
```yaml
|
||||
# .github/workflows/test.yml
|
||||
- name: Run Normalizer Tests
|
||||
run: pytest tests/normalize/normalizers/ -v --cov
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
✅ **112 个测试**全部通过
|
||||
✅ **高覆盖率**: 大部分 normalizer 达到 100%
|
||||
✅ **快速执行**: 5.6 秒完成所有测试
|
||||
✅ **清晰结构**: 每个 normalizer 独立测试文件
|
||||
✅ **易维护**: 遵循 pytest 最佳实践
|
||||
Reference in New Issue
Block a user