| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- """
- 完整集成测试
- 测试后端核心业务逻辑的端到端流程
- """
- import unittest
- from unittest.mock import Mock, patch, MagicMock
- import json
- from datetime import datetime, timedelta
- from src.data.engine import DataEngine
- from src.inspection.services import TaskService, ExecutionService
- from src.billing.services import BillingService
- from src.notification.services import NotificationManager
- from src.gis.services import SpatialQueryService
- from src.governance.validator import DataValidator
-
-
- class TestDataEngineIntegration(unittest.TestCase):
- """数据引擎集成测试"""
-
- def setUp(self):
- self.engine = DataEngine("postgresql://localhost:5432/water_db")
-
- @patch('src.data.engine.session')
- def test_complete_data_lifecycle(self, mock_session):
- """测试完整数据生命周期"""
- # 模拟数据库会话
- mock_session.query.return_value.filter.return_value.all.return_value = []
- mock_session.bulk_save_objects.return_value = Mock()
-
- # 1. 创建设备数据
- device_data = {
- "device_id": "integration_test_device",
- "type": "sensor",
- "location": "building_a",
- "status": "active"
- }
-
- create_result = self.engine.create("devices", device_data)
- self.assertTrue(create_result["success"])
-
- # 2. 读取设备数据
- devices = self.engine.read("devices", {"device_id": "integration_test_device"})
- self.assertEqual(len(devices), 1)
- self.assertEqual(devices[0]["device_id"], "integration_test_device")
-
- # 3. 更新设备状态
- update_result = self.engine.update(
- "devices",
- {"status": "inactive"},
- {"device_id": "integration_test_device"}
- )
- self.assertEqual(update_result["updated_count"], 1)
-
- # 4. 批量导入传感器数据
- sensor_readings = [
- {
- "device_id": "integration_test_device",
- "timestamp": "2026-06-16T10:00:00Z",
- "temperature": 25.5,
- "humidity": 60.2
- },
- {
- "device_id": "integration_test_device",
- "timestamp": "2026-06-16T11:00:00Z",
- "temperature": 26.1,
- "humidity": 61.5
- }
- ]
-
- batch_result = self.engine.batch_import("sensor_data", sensor_readings)
- self.assertEqual(batch_result["imported_count"], 2)
-
- # 5. 删除测试数据
- delete_result = self.engine.delete(
- "devices",
- {"device_id": "integration_test_device"}
- )
- self.assertEqual(delete_result["deleted_count"], 1)
-
- @patch('src.data.engine.session')
- def test_data_validation_integration(self, mock_session):
- """测试数据验证集成"""
- # 模拟验证器
- validator = DataValidator()
-
- # 创建有效数据
- valid_data = {
- "device_id": "valid_device_001",
- "timestamp": "2026-06-16T10:00:00Z",
- "temperature": 25.5,
- "humidity": 60.2
- }
-
- validation_result = validator.validate(valid_data)
- self.assertTrue(validation_result["valid"])
-
- # 创建无效数据
- invalid_data = {
- "device_id": "", # 空设备ID
- "timestamp": "invalid_timestamp", # 无效时间戳
- "temperature": "not_a_number" # 非数字温度
- }
-
- validation_result = validator.validate(invalid_data)
- self.assertFalse(validation_result["valid"])
-
-
- class TestInspectionWorkflowIntegration(unittest.TestCase):
- """巡检工作流集成测试"""
-
- def setUp(self):
- self.task_service = TaskService()
- self.execution_service = ExecutionService()
-
- @patch('src.inspection.services.session')
- @patch('src.inspection.services.DeviceService')
- def test_complete_inspection_workflow(self, mock_device_service, mock_session):
- """测试完整巡检工作流"""
- # 模拟设备服务
- mock_device_service.return_value.check_device_availability.return_value = True
- mock_device_service.return_value.perform_diagnostic.return_value = {
- "status": "normal",
- "metrics": {"temperature": 25.5, "humidity": 60.2}
- }
-
- # 1. 创建巡检任务
- task_data = {
- "task_id": "integration_inspection_001",
- "title": "集成测试巡检",
- "device_ids": ["device_001", "device_002", "device_003"],
- "scheduled_time": "2026-06-17T09:00:00Z",
- "assigned_to": "inspector_01"
- }
-
- with patch.object(self.task_service, 'save_task') as mock_save:
- mock_save.return_value = {"success": True, "task_id": task_data["task_id"]}
-
- task_result = self.task_service.create_task(task_data)
- self.assertTrue(task_result["success"])
-
- # 2. 分配任务
- assignment_result = self.task_service.assign_task(
- task_data["task_id"],
- task_data["assigned_to"]
- )
- self.assertTrue(assignment_result["success"])
-
- # 3. 开始执行
- execution_result = self.execution_service.start_execution(
- task_data["task_id"],
- task_data["assigned_to"]
- )
- self.assertTrue(execution_result["success"])
- self.assertEqual(execution_result["status"], "in_progress")
-
- # 4. 完成执行
- completion_result = self.execution_service.complete_execution(
- task_data["task_id"]
- )
- self.assertTrue(completion_result["success"])
- self.assertEqual(completion_result["status"], "completed")
-
-
- class TestBillingIntegration(unittest.TestCase):
- """计费集成测试"""
-
- def setUp(self):
- self.billing_service = BillingService()
- self.notification_manager = NotificationManager()
-
- @patch('src.billing.services.Tariff')
- @patch('src.billing.services.Bill')
- def test_billing_and_notification_workflow(self, mock_bill_class, mock_tariff_class):
- """测试计费和通知工作流"""
- # 模拟费率
- mock_tariff = Mock()
- mock_tariff.get_price_for_consumption.return_value = 3.5
- mock_tariff_class.get_active_tariff.return_value = mock_tariff
-
- # 1. 生成账单
- customer_id = "integration_customer_001"
- period = {"start_date": "2026-05-01", "end_date": "2026-05-31"}
- consumption_data = {"water_consumption": 15.5}
-
- mock_bill = Mock()
- mock_bill.calculate_total_charge.return_value = 65.25
- mock_bill_class.return_value = mock_bill
-
- bill_result = self.billing_service.generate_monthly_bill(
- customer_id, period, consumption_data
- )
- self.assertTrue(bill_result["success"])
- self.assertEqual(bill_result["total_amount"], 65.25)
-
- # 2. 发送账单通知
- notification_data = {
- "user_id": customer_id,
- "channels": ["email", "sms"],
- "bill_amount": bill_result["total_amount"],
- "due_date": "2026-06-15"
- }
-
- with patch.object(self.notification_manager, 'send_multi_channel_notification') as mock_send:
- mock_send.return_value = {"success": True, "delivered_channels": 2}
-
- notification_result = self.notification_manager.send_multi_channel_notification(notification_data)
- self.assertTrue(notification_result["success"])
- self.assertEqual(notification_result["delivered_channels"], 2)
-
-
- class TestGISIntegration(unittest.TestCase):
- """GIS集成测试"""
-
- def setUp(self):
- self.spatial_service = SpatialQueryService()
-
- @patch('src.gis.services.DeviceLocation')
- @patch('src.gis.services.GeoRegion')
- def test_spatial_analysis_integration(self, mock_geo_region, mock_device_location):
- """测试空间分析集成"""
- # 模拟设备
- devices = []
- for i in range(5):
- device = Mock()
- device.device_id = f"device_{i:03d}"
- device.geometry = Point(108.94 + i * 0.001, 34.26 + i * 0.001)
- devices.append(device)
-
- mock_device_location.query.return_value = devices
-
- # 模拟区域
- region = Mock()
- region.geometry = Polygon([
- [108.94, 34.26],
- [108.95, 34.26],
- [108.95, 34.27],
- [108.94, 34.27],
- [108.94, 34.26]
- ])
- mock_geo_region.query.return_value = [region]
-
- # 1. 查找区域内的设备
- devices_in_region = self.spatial_service.find_devices_in_region(region)
- self.assertGreater(len(devices_in_region), 0)
-
- # 2. 分析设备覆盖
- coverage_analysis = self.spatial_service.analyze_coverage(devices, region)
- self.assertIn("total_coverage", coverage_analysis)
- self.assertIn("coverage_percentage", coverage_analysis)
-
- # 3. 最近邻搜索
- center_point = Point(108.948, 34.265)
- nearest = self.spatial_service.find_nearest_neighbor(center_point, devices)
- self.assertIsNotNone(nearest)
-
-
- class TestGovernanceIntegration(unittest.TestCase):
- """数据治理集成测试"""
-
- def setUp(self):
- self.validator = DataValidator()
-
- def test_data_quality_pipeline(self):
- """测试数据质量管道"""
- # 创建包含各种问题的数据
- problematic_data = [
- {
- "device_id": "device_001",
- "timestamp": "2026-06-16T10:00:00Z",
- "temperature": 25.5,
- "humidity": 60.2
- },
- {
- "device_id": "", # 空设备ID
- "timestamp": "2026-06-16T11:00:00Z",
- "temperature": 200.0, # 异常高温
- "humidity": 150.0 # 超过100%湿度
- },
- {
- "device_id": "device_003",
- "timestamp": "invalid_timestamp", # 无效时间戳
- "temperature": 25.5,
- "humidity": 60.2
- }
- ]
-
- # 逐个验证数据
- valid_data = []
- validation_results = []
-
- for data in problematic_data:
- result = self.validator.validate(data)
- validation_results.append(result)
-
- if result["valid"]:
- valid_data.append(data)
-
- # 验证结果
- self.assertEqual(len(valid_data), 1) # 只有第一行数据有效
- self.assertEqual(len(validation_results), 3)
- self.assertTrue(validation_results[0]["valid"])
- self.assertFalse(validation_results[1]["valid"])
- self.assertFalse(validation_results[2]["valid"])
-
-
- class TestEndToEndIntegration(unittest.TestCase):
- """端到端集成测试"""
-
- def setUp(self):
- self.engine = DataEngine("postgresql://localhost:5432/water_db")
- self.task_service = TaskService()
- self.execution_service = ExecutionService()
- self.billing_service = BillingService()
- self.notification_manager = NotificationManager()
- self.spatial_service = SpatialQueryService()
- self.validator = DataValidator()
-
- @patch('src.data.engine.session')
- @patch('src.inspection.services.session')
- @patch('src.inspection.services.DeviceService')
- @patch('src.billing.services.Tariff')
- @patch('src.billing.services.Bill')
- @patch('src.notification.services.requests')
- @patch('src.gis.services.DeviceLocation')
- @patch('src.gis.services.GeoRegion')
- def test_complete_workflow(self,
- mock_geo_region, mock_device_location,
- mock_requests, mock_bill_class, mock_tariff_class,
- mock_device_service, mock_inspection_session, mock_data_session):
- """测试完整工作流程"""
-
- # 设置所有模拟对象
- mock_data_session.query.return_value.filter.return_value.all.return_value = []
- mock_data_session.bulk_save_objects.return_value = Mock()
-
- mock_device_service.return_value.check_device_availability.return_value = True
- mock_device_service.return_value.perform_diagnostic.return_value = {
- "status": "normal",
- "metrics": {"temperature": 25.5, "humidity": 60.2}
- }
-
- mock_tariff = Mock()
- mock_tariff.get_price_for_consumption.return_value = 3.5
- mock_tariff_class.get_active_tariff.return_value = mock_tariff
-
- mock_bill = Mock()
- mock_bill.calculate_total_charge.return_value = 65.25
- mock_bill_class.return_value = mock_bill
-
- mock_response = Mock()
- mock_response.status_code = 200
- mock_response.json.return_value = {"success": True}
- mock_requests.post.return_value = mock_response
-
- devices = [Mock(device_id=f"device_{i:03d}", geometry=Point(108.94 + i * 0.001, 34.26 + i * 0.001)) for i in range(3)]
- mock_device_location.query.return_value = devices
-
- region = Mock(geometry=Polygon([
- [108.94, 34.26], [108.95, 34.26], [108.95, 34.27], [108.94, 34.27], [108.94, 34.26]
- ]))
- mock_geo_region.query.return_value = [region]
-
- # 1. 设备注册和数据采集
- device_data = {
- "device_id": "e2e_test_device",
- "type": "sensor",
- "location": "building_a"
- }
-
- create_result = self.engine.create("devices", device_data)
- self.assertTrue(create_result["success"])
-
- # 2. 创建巡检任务
- task_data = {
- "task_id": "e2e_inspection_001",
- "title": "端到端测试巡检",
- "device_ids": ["e2e_test_device"],
- "scheduled_time": "2026-06-17T09:00:00Z"
- }
-
- with patch.object(self.task_service, 'save_task') as mock_save:
- mock_save.return_value = {"success": True, "task_id": task_data["task_id"]}
- task_result = self.task_service.create_task(task_data)
- self.assertTrue(task_result["success"])
-
- # 3. 执行巡检
- execution_result = self.execution_service.execute_inspection(task_data["task_id"])
- self.assertTrue(execution_result["success"])
-
- # 4. 生成账单
- bill_result = self.billing_service.generate_monthly_bill(
- "customer_001",
- {"start_date": "2026-05-01", "end_date": "2026-05-31"},
- {"water_consumption": 15.5}
- )
- self.assertTrue(bill_result["success"])
-
- # 5. 发送通知
- notification_result = self.notification_manager.send_multi_channel_notification({
- "user_id": "customer_001",
- "channels": ["email"],
- "message": "账单已生成",
- "bill_amount": bill_result["total_amount"]
- })
- self.assertTrue(notification_result["success"])
-
- # 6. 空间分析
- spatial_result = self.spatial_service.find_devices_in_region(region)
- self.assertGreater(len(spatial_result), 0)
-
- # 7. 数据验证
- valid_result = self.validator.validate({
- "device_id": "e2e_test_device",
- "timestamp": "2026-06-16T10:00:00Z",
- "temperature": 25.5,
- "humidity": 60.2
- })
- self.assertTrue(valid_result["valid"])
-
-
- if __name__ == '__main__':
- unittest.main()
|