xx
This commit is contained in:
331
test_process_excel.py
Normal file
331
test_process_excel.py
Normal file
@@ -0,0 +1,331 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
财务Excel数据处理程序的单元测试
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import json
|
||||
import os
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.worksheet.worksheet import Worksheet
|
||||
|
||||
# 导入被测试的模块
|
||||
try:
|
||||
from process_excel_optimized import (
|
||||
Order, FinancialRecord, ProcessingStats,
|
||||
MergedCellCache, get_cell_value, validate_amount
|
||||
)
|
||||
USE_OPTIMIZED = True
|
||||
except ImportError:
|
||||
USE_OPTIMIZED = False
|
||||
print("警告: 无法导入优化版本,部分测试将被跳过")
|
||||
|
||||
|
||||
class TestOrder(unittest.TestCase):
|
||||
"""测试Order数据类"""
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_order_creation(self):
|
||||
"""测试订单创建"""
|
||||
order = Order(
|
||||
OrderNum="TEST001",
|
||||
Amount=1000.50,
|
||||
AccountName="测试账户"
|
||||
)
|
||||
|
||||
self.assertEqual(order.OrderNum, "TEST001")
|
||||
self.assertEqual(order.Amount, 1000.50)
|
||||
self.assertEqual(order.AccountName, "测试账户")
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_order_to_dict(self):
|
||||
"""测试订单转换为字典"""
|
||||
order = Order(
|
||||
OrderNum="TEST001",
|
||||
Amount=1000.50,
|
||||
AccountName="测试账户"
|
||||
)
|
||||
|
||||
result = order.to_dict()
|
||||
|
||||
self.assertIsInstance(result, dict)
|
||||
self.assertEqual(result["OrderNum"], "TEST001")
|
||||
self.assertEqual(result["Amount"], 1000.50)
|
||||
self.assertEqual(result["AccountName"], "测试账户")
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_order_with_none_values(self):
|
||||
"""测试订单号为空的情况"""
|
||||
order = Order(
|
||||
OrderNum=None,
|
||||
Amount=1000.50,
|
||||
AccountName="测试账户"
|
||||
)
|
||||
|
||||
self.assertIsNone(order.OrderNum)
|
||||
self.assertEqual(order.Amount, 1000.50)
|
||||
|
||||
|
||||
class TestFinancialRecord(unittest.TestCase):
|
||||
"""测试FinancialRecord数据类"""
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_record_creation(self):
|
||||
"""测试财务记录创建"""
|
||||
orders = [
|
||||
Order("TEST001", 1000.0, "账户1"),
|
||||
Order("TEST002", 2000.0, "账户2")
|
||||
]
|
||||
|
||||
record = FinancialRecord(
|
||||
ReceivedAmount=2975.0,
|
||||
HandlingFee=25.0,
|
||||
Order=orders,
|
||||
checkRes=True
|
||||
)
|
||||
|
||||
self.assertEqual(record.ReceivedAmount, 2975.0)
|
||||
self.assertEqual(record.HandlingFee, 25.0)
|
||||
self.assertEqual(len(record.Order), 2)
|
||||
self.assertTrue(record.checkRes)
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_record_to_dict(self):
|
||||
"""测试财务记录转换为字典"""
|
||||
orders = [Order("TEST001", 1000.0, "账户1")]
|
||||
record = FinancialRecord(
|
||||
ReceivedAmount=1000.0,
|
||||
HandlingFee=0.0,
|
||||
Order=orders,
|
||||
checkRes=True
|
||||
)
|
||||
|
||||
result = record.to_dict()
|
||||
|
||||
self.assertIsInstance(result, dict)
|
||||
self.assertEqual(result["ReceivedAmount"], 1000.0)
|
||||
self.assertIsInstance(result["Order"], list)
|
||||
self.assertEqual(len(result["Order"]), 1)
|
||||
|
||||
|
||||
class TestProcessingStats(unittest.TestCase):
|
||||
"""测试ProcessingStats统计类"""
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_stats_initialization(self):
|
||||
"""测试统计对象初始化"""
|
||||
stats = ProcessingStats()
|
||||
|
||||
self.assertEqual(stats.total_records, 0)
|
||||
self.assertEqual(stats.valid_records, 0)
|
||||
self.assertEqual(stats.invalid_records, 0)
|
||||
self.assertEqual(stats.total_orders, 0)
|
||||
self.assertEqual(stats.check_failed_records, 0)
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_stats_update(self):
|
||||
"""测试统计数据更新"""
|
||||
stats = ProcessingStats()
|
||||
|
||||
stats.total_records = 10
|
||||
stats.valid_records = 8
|
||||
stats.invalid_records = 2
|
||||
stats.total_orders = 25
|
||||
|
||||
self.assertEqual(stats.total_records, 10)
|
||||
self.assertEqual(stats.valid_records, 8)
|
||||
self.assertEqual(stats.invalid_records, 2)
|
||||
self.assertEqual(stats.total_orders, 25)
|
||||
|
||||
|
||||
class TestMergedCellCache(unittest.TestCase):
|
||||
"""测试MergedCellCache缓存类"""
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_cache_creation(self):
|
||||
"""测试缓存创建"""
|
||||
# 创建模拟的合并单元格范围
|
||||
mock_range = Mock()
|
||||
mock_range.min_row = 2
|
||||
mock_range.max_row = 4
|
||||
mock_range.min_col = 6
|
||||
mock_range.max_col = 6
|
||||
|
||||
cache = MergedCellCache([mock_range])
|
||||
|
||||
# 测试缓存是否正确识别合并单元格
|
||||
self.assertTrue(cache.is_merged(2, 6))
|
||||
self.assertTrue(cache.is_merged(3, 6))
|
||||
self.assertTrue(cache.is_merged(4, 6))
|
||||
self.assertFalse(cache.is_merged(5, 6))
|
||||
self.assertFalse(cache.is_merged(2, 7))
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_cache_get_merged_range(self):
|
||||
"""测试获取合并范围"""
|
||||
mock_range = Mock()
|
||||
mock_range.min_row = 2
|
||||
mock_range.max_row = 4
|
||||
mock_range.min_col = 6
|
||||
mock_range.max_col = 6
|
||||
|
||||
cache = MergedCellCache([mock_range])
|
||||
|
||||
# 测试获取合并范围
|
||||
result = cache.get_merged_range(3, 6)
|
||||
self.assertIsNotNone(result)
|
||||
|
||||
# 测试非合并单元格
|
||||
result = cache.get_merged_range(10, 10)
|
||||
self.assertIsNone(result)
|
||||
|
||||
|
||||
class TestValidateAmount(unittest.TestCase):
|
||||
"""测试金额验证函数"""
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_validate_exact_match(self):
|
||||
"""测试金额完全匹配"""
|
||||
orders = [
|
||||
Order("TEST001", 1000.0, "账户1"),
|
||||
Order("TEST002", 975.0, "账户2")
|
||||
]
|
||||
|
||||
result = validate_amount(1975.0, 0.0, orders)
|
||||
self.assertTrue(result)
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_validate_with_handling_fee(self):
|
||||
"""测试包含手续费的金额验证"""
|
||||
orders = [
|
||||
Order("TEST001", 2000.0, "账户1")
|
||||
]
|
||||
|
||||
result = validate_amount(1975.0, 25.0, orders)
|
||||
self.assertTrue(result)
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_validate_within_tolerance(self):
|
||||
"""测试在容差范围内的金额"""
|
||||
orders = [
|
||||
Order("TEST001", 1000.005, "账户1")
|
||||
]
|
||||
|
||||
# 差额在0.01容差范围内
|
||||
result = validate_amount(1000.0, 0.0, orders)
|
||||
self.assertTrue(result)
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_validate_mismatch(self):
|
||||
"""测试金额不匹配"""
|
||||
orders = [
|
||||
Order("TEST001", 1000.0, "账户1"),
|
||||
Order("TEST002", 500.0, "账户2")
|
||||
]
|
||||
|
||||
result = validate_amount(1000.0, 0.0, orders)
|
||||
self.assertFalse(result)
|
||||
|
||||
@unittest.skipIf(not USE_OPTIMIZED, "需要优化版本")
|
||||
def test_validate_with_none_amount(self):
|
||||
"""测试包含空金额的订单"""
|
||||
orders = [
|
||||
Order("TEST001", 1000.0, "账户1"),
|
||||
Order("TEST002", None, "账户2") # 空金额应被忽略
|
||||
]
|
||||
|
||||
result = validate_amount(1000.0, 0.0, orders)
|
||||
self.assertTrue(result)
|
||||
|
||||
|
||||
class TestIntegration(unittest.TestCase):
|
||||
"""集成测试"""
|
||||
|
||||
def test_json_output_format(self):
|
||||
"""测试JSON输出格式"""
|
||||
# 检查res.json是否存在
|
||||
if not os.path.exists('res.json'):
|
||||
self.skipTest("res.json文件不存在")
|
||||
|
||||
# 读取JSON文件
|
||||
with open('res.json', 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
# 验证数据结构
|
||||
self.assertIsInstance(data, list)
|
||||
|
||||
if len(data) > 0:
|
||||
record = data[0]
|
||||
|
||||
# 验证必需字段
|
||||
self.assertIn("ReceivedAmount", record)
|
||||
self.assertIn("HandlingFee", record)
|
||||
self.assertIn("Order", record)
|
||||
self.assertIn("checkRes", record)
|
||||
|
||||
# 验证Order结构
|
||||
self.assertIsInstance(record["Order"], list)
|
||||
if len(record["Order"]) > 0:
|
||||
order = record["Order"][0]
|
||||
self.assertIn("OrderNum", order)
|
||||
self.assertIn("Amount", order)
|
||||
self.assertIn("AccountName", order)
|
||||
|
||||
|
||||
class TestConfigIntegration(unittest.TestCase):
|
||||
"""配置文件集成测试"""
|
||||
|
||||
def test_config_file_exists(self):
|
||||
"""测试配置文件是否存在"""
|
||||
self.assertTrue(
|
||||
os.path.exists('config.ini'),
|
||||
"config.ini配置文件应该存在"
|
||||
)
|
||||
|
||||
def test_exchange_rate_file(self):
|
||||
"""测试汇率文件"""
|
||||
if not os.path.exists('exchange_rate.txt'):
|
||||
self.skipTest("exchange_rate.txt文件不存在")
|
||||
|
||||
with open('exchange_rate.txt', 'r', encoding='utf-8') as f:
|
||||
content = f.read().strip()
|
||||
|
||||
# 验证可以转换为浮点数
|
||||
try:
|
||||
rate = float(content)
|
||||
self.assertGreater(rate, 0)
|
||||
self.assertLess(rate, 100)
|
||||
except ValueError:
|
||||
self.fail("汇率文件内容无法转换为数字")
|
||||
|
||||
|
||||
def run_tests():
|
||||
"""运行所有测试"""
|
||||
# 创建测试套件
|
||||
loader = unittest.TestLoader()
|
||||
suite = unittest.TestSuite()
|
||||
|
||||
# 添加所有测试类
|
||||
suite.addTests(loader.loadTestsFromTestCase(TestOrder))
|
||||
suite.addTests(loader.loadTestsFromTestCase(TestFinancialRecord))
|
||||
suite.addTests(loader.loadTestsFromTestCase(TestProcessingStats))
|
||||
suite.addTests(loader.loadTestsFromTestCase(TestMergedCellCache))
|
||||
suite.addTests(loader.loadTestsFromTestCase(TestValidateAmount))
|
||||
suite.addTests(loader.loadTestsFromTestCase(TestIntegration))
|
||||
suite.addTests(loader.loadTestsFromTestCase(TestConfigIntegration))
|
||||
|
||||
# 运行测试
|
||||
runner = unittest.TextTestRunner(verbosity=2)
|
||||
result = runner.run(suite)
|
||||
|
||||
# 返回测试结果
|
||||
return result.wasSuccessful()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
success = run_tests()
|
||||
exit(0 if success else 1)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user