智慧水务管理系统 - 精河县供水工程综合管理平台

test_full_integration.py 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. """
  2. 完整集成测试
  3. 测试后端核心业务逻辑的端到端流程
  4. """
  5. import unittest
  6. from unittest.mock import Mock, patch, MagicMock
  7. import json
  8. from datetime import datetime, timedelta
  9. from src.data.engine import DataEngine
  10. from src.inspection.services import TaskService, ExecutionService
  11. from src.billing.services import BillingService
  12. from src.notification.services import NotificationManager
  13. from src.gis.services import SpatialQueryService
  14. from src.governance.validator import DataValidator
  15. class TestDataEngineIntegration(unittest.TestCase):
  16. """数据引擎集成测试"""
  17. def setUp(self):
  18. self.engine = DataEngine("postgresql://localhost:5432/water_db")
  19. @patch('src.data.engine.session')
  20. def test_complete_data_lifecycle(self, mock_session):
  21. """测试完整数据生命周期"""
  22. # 模拟数据库会话
  23. mock_session.query.return_value.filter.return_value.all.return_value = []
  24. mock_session.bulk_save_objects.return_value = Mock()
  25. # 1. 创建设备数据
  26. device_data = {
  27. "device_id": "integration_test_device",
  28. "type": "sensor",
  29. "location": "building_a",
  30. "status": "active"
  31. }
  32. create_result = self.engine.create("devices", device_data)
  33. self.assertTrue(create_result["success"])
  34. # 2. 读取设备数据
  35. devices = self.engine.read("devices", {"device_id": "integration_test_device"})
  36. self.assertEqual(len(devices), 1)
  37. self.assertEqual(devices[0]["device_id"], "integration_test_device")
  38. # 3. 更新设备状态
  39. update_result = self.engine.update(
  40. "devices",
  41. {"status": "inactive"},
  42. {"device_id": "integration_test_device"}
  43. )
  44. self.assertEqual(update_result["updated_count"], 1)
  45. # 4. 批量导入传感器数据
  46. sensor_readings = [
  47. {
  48. "device_id": "integration_test_device",
  49. "timestamp": "2026-06-16T10:00:00Z",
  50. "temperature": 25.5,
  51. "humidity": 60.2
  52. },
  53. {
  54. "device_id": "integration_test_device",
  55. "timestamp": "2026-06-16T11:00:00Z",
  56. "temperature": 26.1,
  57. "humidity": 61.5
  58. }
  59. ]
  60. batch_result = self.engine.batch_import("sensor_data", sensor_readings)
  61. self.assertEqual(batch_result["imported_count"], 2)
  62. # 5. 删除测试数据
  63. delete_result = self.engine.delete(
  64. "devices",
  65. {"device_id": "integration_test_device"}
  66. )
  67. self.assertEqual(delete_result["deleted_count"], 1)
  68. @patch('src.data.engine.session')
  69. def test_data_validation_integration(self, mock_session):
  70. """测试数据验证集成"""
  71. # 模拟验证器
  72. validator = DataValidator()
  73. # 创建有效数据
  74. valid_data = {
  75. "device_id": "valid_device_001",
  76. "timestamp": "2026-06-16T10:00:00Z",
  77. "temperature": 25.5,
  78. "humidity": 60.2
  79. }
  80. validation_result = validator.validate(valid_data)
  81. self.assertTrue(validation_result["valid"])
  82. # 创建无效数据
  83. invalid_data = {
  84. "device_id": "", # 空设备ID
  85. "timestamp": "invalid_timestamp", # 无效时间戳
  86. "temperature": "not_a_number" # 非数字温度
  87. }
  88. validation_result = validator.validate(invalid_data)
  89. self.assertFalse(validation_result["valid"])
  90. class TestInspectionWorkflowIntegration(unittest.TestCase):
  91. """巡检工作流集成测试"""
  92. def setUp(self):
  93. self.task_service = TaskService()
  94. self.execution_service = ExecutionService()
  95. @patch('src.inspection.services.session')
  96. @patch('src.inspection.services.DeviceService')
  97. def test_complete_inspection_workflow(self, mock_device_service, mock_session):
  98. """测试完整巡检工作流"""
  99. # 模拟设备服务
  100. mock_device_service.return_value.check_device_availability.return_value = True
  101. mock_device_service.return_value.perform_diagnostic.return_value = {
  102. "status": "normal",
  103. "metrics": {"temperature": 25.5, "humidity": 60.2}
  104. }
  105. # 1. 创建巡检任务
  106. task_data = {
  107. "task_id": "integration_inspection_001",
  108. "title": "集成测试巡检",
  109. "device_ids": ["device_001", "device_002", "device_003"],
  110. "scheduled_time": "2026-06-17T09:00:00Z",
  111. "assigned_to": "inspector_01"
  112. }
  113. with patch.object(self.task_service, 'save_task') as mock_save:
  114. mock_save.return_value = {"success": True, "task_id": task_data["task_id"]}
  115. task_result = self.task_service.create_task(task_data)
  116. self.assertTrue(task_result["success"])
  117. # 2. 分配任务
  118. assignment_result = self.task_service.assign_task(
  119. task_data["task_id"],
  120. task_data["assigned_to"]
  121. )
  122. self.assertTrue(assignment_result["success"])
  123. # 3. 开始执行
  124. execution_result = self.execution_service.start_execution(
  125. task_data["task_id"],
  126. task_data["assigned_to"]
  127. )
  128. self.assertTrue(execution_result["success"])
  129. self.assertEqual(execution_result["status"], "in_progress")
  130. # 4. 完成执行
  131. completion_result = self.execution_service.complete_execution(
  132. task_data["task_id"]
  133. )
  134. self.assertTrue(completion_result["success"])
  135. self.assertEqual(completion_result["status"], "completed")
  136. class TestBillingIntegration(unittest.TestCase):
  137. """计费集成测试"""
  138. def setUp(self):
  139. self.billing_service = BillingService()
  140. self.notification_manager = NotificationManager()
  141. @patch('src.billing.services.Tariff')
  142. @patch('src.billing.services.Bill')
  143. def test_billing_and_notification_workflow(self, mock_bill_class, mock_tariff_class):
  144. """测试计费和通知工作流"""
  145. # 模拟费率
  146. mock_tariff = Mock()
  147. mock_tariff.get_price_for_consumption.return_value = 3.5
  148. mock_tariff_class.get_active_tariff.return_value = mock_tariff
  149. # 1. 生成账单
  150. customer_id = "integration_customer_001"
  151. period = {"start_date": "2026-05-01", "end_date": "2026-05-31"}
  152. consumption_data = {"water_consumption": 15.5}
  153. mock_bill = Mock()
  154. mock_bill.calculate_total_charge.return_value = 65.25
  155. mock_bill_class.return_value = mock_bill
  156. bill_result = self.billing_service.generate_monthly_bill(
  157. customer_id, period, consumption_data
  158. )
  159. self.assertTrue(bill_result["success"])
  160. self.assertEqual(bill_result["total_amount"], 65.25)
  161. # 2. 发送账单通知
  162. notification_data = {
  163. "user_id": customer_id,
  164. "channels": ["email", "sms"],
  165. "bill_amount": bill_result["total_amount"],
  166. "due_date": "2026-06-15"
  167. }
  168. with patch.object(self.notification_manager, 'send_multi_channel_notification') as mock_send:
  169. mock_send.return_value = {"success": True, "delivered_channels": 2}
  170. notification_result = self.notification_manager.send_multi_channel_notification(notification_data)
  171. self.assertTrue(notification_result["success"])
  172. self.assertEqual(notification_result["delivered_channels"], 2)
  173. class TestGISIntegration(unittest.TestCase):
  174. """GIS集成测试"""
  175. def setUp(self):
  176. self.spatial_service = SpatialQueryService()
  177. @patch('src.gis.services.DeviceLocation')
  178. @patch('src.gis.services.GeoRegion')
  179. def test_spatial_analysis_integration(self, mock_geo_region, mock_device_location):
  180. """测试空间分析集成"""
  181. # 模拟设备
  182. devices = []
  183. for i in range(5):
  184. device = Mock()
  185. device.device_id = f"device_{i:03d}"
  186. device.geometry = Point(108.94 + i * 0.001, 34.26 + i * 0.001)
  187. devices.append(device)
  188. mock_device_location.query.return_value = devices
  189. # 模拟区域
  190. region = Mock()
  191. region.geometry = Polygon([
  192. [108.94, 34.26],
  193. [108.95, 34.26],
  194. [108.95, 34.27],
  195. [108.94, 34.27],
  196. [108.94, 34.26]
  197. ])
  198. mock_geo_region.query.return_value = [region]
  199. # 1. 查找区域内的设备
  200. devices_in_region = self.spatial_service.find_devices_in_region(region)
  201. self.assertGreater(len(devices_in_region), 0)
  202. # 2. 分析设备覆盖
  203. coverage_analysis = self.spatial_service.analyze_coverage(devices, region)
  204. self.assertIn("total_coverage", coverage_analysis)
  205. self.assertIn("coverage_percentage", coverage_analysis)
  206. # 3. 最近邻搜索
  207. center_point = Point(108.948, 34.265)
  208. nearest = self.spatial_service.find_nearest_neighbor(center_point, devices)
  209. self.assertIsNotNone(nearest)
  210. class TestGovernanceIntegration(unittest.TestCase):
  211. """数据治理集成测试"""
  212. def setUp(self):
  213. self.validator = DataValidator()
  214. def test_data_quality_pipeline(self):
  215. """测试数据质量管道"""
  216. # 创建包含各种问题的数据
  217. problematic_data = [
  218. {
  219. "device_id": "device_001",
  220. "timestamp": "2026-06-16T10:00:00Z",
  221. "temperature": 25.5,
  222. "humidity": 60.2
  223. },
  224. {
  225. "device_id": "", # 空设备ID
  226. "timestamp": "2026-06-16T11:00:00Z",
  227. "temperature": 200.0, # 异常高温
  228. "humidity": 150.0 # 超过100%湿度
  229. },
  230. {
  231. "device_id": "device_003",
  232. "timestamp": "invalid_timestamp", # 无效时间戳
  233. "temperature": 25.5,
  234. "humidity": 60.2
  235. }
  236. ]
  237. # 逐个验证数据
  238. valid_data = []
  239. validation_results = []
  240. for data in problematic_data:
  241. result = self.validator.validate(data)
  242. validation_results.append(result)
  243. if result["valid"]:
  244. valid_data.append(data)
  245. # 验证结果
  246. self.assertEqual(len(valid_data), 1) # 只有第一行数据有效
  247. self.assertEqual(len(validation_results), 3)
  248. self.assertTrue(validation_results[0]["valid"])
  249. self.assertFalse(validation_results[1]["valid"])
  250. self.assertFalse(validation_results[2]["valid"])
  251. class TestEndToEndIntegration(unittest.TestCase):
  252. """端到端集成测试"""
  253. def setUp(self):
  254. self.engine = DataEngine("postgresql://localhost:5432/water_db")
  255. self.task_service = TaskService()
  256. self.execution_service = ExecutionService()
  257. self.billing_service = BillingService()
  258. self.notification_manager = NotificationManager()
  259. self.spatial_service = SpatialQueryService()
  260. self.validator = DataValidator()
  261. @patch('src.data.engine.session')
  262. @patch('src.inspection.services.session')
  263. @patch('src.inspection.services.DeviceService')
  264. @patch('src.billing.services.Tariff')
  265. @patch('src.billing.services.Bill')
  266. @patch('src.notification.services.requests')
  267. @patch('src.gis.services.DeviceLocation')
  268. @patch('src.gis.services.GeoRegion')
  269. def test_complete_workflow(self,
  270. mock_geo_region, mock_device_location,
  271. mock_requests, mock_bill_class, mock_tariff_class,
  272. mock_device_service, mock_inspection_session, mock_data_session):
  273. """测试完整工作流程"""
  274. # 设置所有模拟对象
  275. mock_data_session.query.return_value.filter.return_value.all.return_value = []
  276. mock_data_session.bulk_save_objects.return_value = Mock()
  277. mock_device_service.return_value.check_device_availability.return_value = True
  278. mock_device_service.return_value.perform_diagnostic.return_value = {
  279. "status": "normal",
  280. "metrics": {"temperature": 25.5, "humidity": 60.2}
  281. }
  282. mock_tariff = Mock()
  283. mock_tariff.get_price_for_consumption.return_value = 3.5
  284. mock_tariff_class.get_active_tariff.return_value = mock_tariff
  285. mock_bill = Mock()
  286. mock_bill.calculate_total_charge.return_value = 65.25
  287. mock_bill_class.return_value = mock_bill
  288. mock_response = Mock()
  289. mock_response.status_code = 200
  290. mock_response.json.return_value = {"success": True}
  291. mock_requests.post.return_value = mock_response
  292. 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)]
  293. mock_device_location.query.return_value = devices
  294. region = Mock(geometry=Polygon([
  295. [108.94, 34.26], [108.95, 34.26], [108.95, 34.27], [108.94, 34.27], [108.94, 34.26]
  296. ]))
  297. mock_geo_region.query.return_value = [region]
  298. # 1. 设备注册和数据采集
  299. device_data = {
  300. "device_id": "e2e_test_device",
  301. "type": "sensor",
  302. "location": "building_a"
  303. }
  304. create_result = self.engine.create("devices", device_data)
  305. self.assertTrue(create_result["success"])
  306. # 2. 创建巡检任务
  307. task_data = {
  308. "task_id": "e2e_inspection_001",
  309. "title": "端到端测试巡检",
  310. "device_ids": ["e2e_test_device"],
  311. "scheduled_time": "2026-06-17T09:00:00Z"
  312. }
  313. with patch.object(self.task_service, 'save_task') as mock_save:
  314. mock_save.return_value = {"success": True, "task_id": task_data["task_id"]}
  315. task_result = self.task_service.create_task(task_data)
  316. self.assertTrue(task_result["success"])
  317. # 3. 执行巡检
  318. execution_result = self.execution_service.execute_inspection(task_data["task_id"])
  319. self.assertTrue(execution_result["success"])
  320. # 4. 生成账单
  321. bill_result = self.billing_service.generate_monthly_bill(
  322. "customer_001",
  323. {"start_date": "2026-05-01", "end_date": "2026-05-31"},
  324. {"water_consumption": 15.5}
  325. )
  326. self.assertTrue(bill_result["success"])
  327. # 5. 发送通知
  328. notification_result = self.notification_manager.send_multi_channel_notification({
  329. "user_id": "customer_001",
  330. "channels": ["email"],
  331. "message": "账单已生成",
  332. "bill_amount": bill_result["total_amount"]
  333. })
  334. self.assertTrue(notification_result["success"])
  335. # 6. 空间分析
  336. spatial_result = self.spatial_service.find_devices_in_region(region)
  337. self.assertGreater(len(spatial_result), 0)
  338. # 7. 数据验证
  339. valid_result = self.validator.validate({
  340. "device_id": "e2e_test_device",
  341. "timestamp": "2026-06-16T10:00:00Z",
  342. "temperature": 25.5,
  343. "humidity": 60.2
  344. })
  345. self.assertTrue(valid_result["valid"])
  346. if __name__ == '__main__':
  347. unittest.main()