unit uUnitTests; interface uses TestFramework, SysUtils, Classes, System.JSON, uExceptionHandler, uLogManager, uConfigManager, uBusinessServices, uCommonUtils; type TTestExceptionHandler = class(TTestCase) published procedure TestBaseException; procedure TestNetworkException; procedure TestDataException; procedure TestBusinessException; procedure TestDeviceException; procedure TestValidationException; procedure TestExceptionHandler; end; TTestLogManager = class(TTestCase) published procedure TestLogLevels; procedure TestLogCategories; procedure TestPerformanceLogger; procedure TestLogExport; procedure TestUIMonitoring; procedure TestNetworkMonitoring; procedure TestFormMonitoring; procedure TestDataOperationMonitoring; procedure TestLogCategoriesFilter; end; TTestConfigManager = class(TTestCase) published procedure TestConfigLoading; procedure TestConfigSaving; procedure TestConfigTypes; procedure TestAppConfig; procedure TestAppConfigExtended; procedure TestConfigArrayAndObject; end; TTestBusinessServices = class(TTestCase) published procedure TestAuthService; procedure TestAuthServiceLogout; procedure TestAuthServiceRefreshToken; procedure TestWorkOrderService; procedure TestWorkOrderServiceCreate; procedure TestWorkOrderServiceUpdateStatus; procedure TestWorkOrderServiceReportProduction; procedure TestDeviceService; procedure TestDeviceServiceConnectDisconnect; procedure TestDeviceServiceSendCommand; procedure TestSyncService; procedure TestSyncServiceBatch; procedure TestSyncServiceRetry; procedure TestProductionReportingService; procedure TestProductionReportingServiceValidateUser; procedure TestProductionReportingServiceGetWorkOrderInfo; procedure TestProductionReportingServiceGetProcessList; procedure TestProductionReportingServiceValidateGoodsNo; procedure TestProductionReportingServiceSubmitData; procedure TestDeviceConfigService; procedure TestDataAccessService; end; TTestCommonUtils = class(TTestCase) published procedure TestValidator; procedure TestStringHelper; procedure TestDateTimeHelper; procedure TestFileHelper; procedure TestJSONHelper; end; implementation { TTestExceptionHandler } procedure TTestExceptionHandler.TestBaseException; var Ex: EBaseException; JSON: TJSONObject; begin Ex := EBaseException.Create('Test exception', 1001, 'Test'); try CheckEquals('Test exception', Ex.Message); CheckEquals(1001, Ex.ErrorCode); CheckEquals('Test', Ex.ErrorType); JSON := Ex.ToJSON; try CheckNotNull(JSON); CheckEquals('Test exception', JSON.GetValue('message').Value); finally JSON.Free; end; finally Ex.Free; end; end; procedure TTestExceptionHandler.TestNetworkException; var Ex: ENetworkException; begin Ex := ENetworkException.Create('Network error', 2001); try CheckEquals('Network error', Ex.Message); CheckEquals(2001, Ex.ErrorCode); CheckEquals('Network', Ex.ErrorType); finally Ex.Free; end; end; procedure TTestExceptionHandler.TestDataException; var Ex: EDataException; begin Ex := EDataException.Create('Data error', 3001); try CheckEquals('Data error', Ex.Message); CheckEquals(3001, Ex.ErrorCode); CheckEquals('Data', Ex.ErrorType); finally Ex.Free; end; end; procedure TTestExceptionHandler.TestBusinessException; var Ex: EBusinessException; begin Ex := EBusinessException.Create('Business error', 4001); try CheckEquals('Business error', Ex.Message); CheckEquals(4001, Ex.ErrorCode); CheckEquals('Business', Ex.ErrorType); finally Ex.Free; end; end; procedure TTestExceptionHandler.TestDeviceException; var Ex: EDeviceException; begin Ex := EDeviceException.Create('Device error', 5001); try CheckEquals('Device error', Ex.Message); CheckEquals(5001, Ex.ErrorCode); CheckEquals('Device', Ex.ErrorType); finally Ex.Free; end; end; procedure TTestExceptionHandler.TestValidationException; var Ex: EValidationException; begin Ex := EValidationException.Create('Field', 'Value', 'Validation error'); try CheckEquals('Validation error', Ex.Message); CheckEquals('Field', Ex.FieldName); CheckEquals('Value', Ex.FieldValue); finally Ex.Free; end; end; procedure TTestExceptionHandler.TestExceptionHandler; var Handler: TExceptionHandler; Ex: Exception; begin Handler := TExceptionHandler.Create; try Ex := Exception.Create('Test exception'); try Handler.HandleException(Ex); // 验证没有异常抛出 finally Ex.Free; end; finally Handler.Free; end; end; { TTestLogManager } procedure TTestLogManager.TestLogLevels; begin LogManager.Trace('Test trace'); LogManager.Debug('Test debug'); LogManager.Info('Test info'); LogManager.Warn('Test warn'); LogManager.Error('Test error'); LogManager.Fatal('Test fatal'); // 验证没有异常抛出 end; procedure TTestLogManager.TestLogCategories; begin LogManager.TraceCategory(lcSystem, 'Test system'); LogManager.DebugCategory(lcNetwork, 'Test network'); LogManager.InfoCategory(lcDatabase, 'Test database'); LogManager.WarnCategory(lcBusiness, 'Test business'); LogManager.ErrorCategory(lcDevice, 'Test device'); LogManager.FatalCategory(lcUI, 'Test UI'); // 验证没有异常抛出 end; procedure TTestLogManager.TestPerformanceLogger; var Logger: TPerformanceLogger; StartTime: TDateTime; Elapsed: Integer; begin StartTime := Now; Logger := TPerformanceLogger.Create('Test operation'); try // 模拟操作 Sleep(100); finally Logger.Free; end; Elapsed := MilliSecondsBetween(Now, StartTime); Check(Elapsed >= 100, 'Performance logger should record time'); end; procedure TTestLogManager.TestLogExport; var JSONArray: TJSONArray; begin LogManager.Info('Test log for export'); JSONArray := LogManager.ExportToJSON; try CheckNotNull(JSONArray); Check(JSONArray.Count > 0, 'Log export should return data'); finally JSONArray.Free; end; end; procedure TTestLogManager.TestUIMonitoring; begin LogManager.LogUIOperation('Click', 'Button1', 50); LogManager.LogUIOperation('Select', 'ComboBox1', -1); Check(True, 'UI monitoring should not throw exception'); end; procedure TTestLogManager.TestNetworkMonitoring; begin LogManager.LogNetworkRequest('http://example.com/api', 'GET', 200, 150); LogManager.LogNetworkRequest('http://example.com/api', 'POST', 201, 200); LogManager.LogNetworkRequest('http://example.com/api', 'GET', 404, 100); LogManager.LogNetworkRequest('http://example.com/api', 'POST', 500, 300); Check(True, 'Network monitoring should not throw exception'); end; procedure TTestLogManager.TestFormMonitoring; begin LogManager.LogFormShow('MainForm', 100); LogManager.LogFormShow('LoginForm', -1); LogManager.LogFormClose('MainForm', 50); LogManager.LogFormClose('LoginForm', -1); Check(True, 'Form monitoring should not throw exception'); end; procedure TTestLogManager.TestDataOperationMonitoring; begin LogManager.LogDataOperation('INSERT', 10, 25); LogManager.LogDataOperation('UPDATE', 5, -1); LogManager.LogDataOperation('DELETE', 3, 15); Check(True, 'Data operation monitoring should not throw exception'); end; procedure TTestLogManager.TestLogCategoriesFilter; var Logs: TArray; begin LogManager.ClearLogs; LogManager.InfoCategory(lcBusiness, 'Business log 1'); LogManager.InfoCategory(lcDevice, 'Device log 1'); LogManager.InfoCategory(lcNetwork, 'Network log 1'); Logs := LogManager.GetLogs(llInfo, [lcBusiness, lcDevice]); Check(Length(Logs) >= 0, 'Should return filtered logs'); end; { TTestConfigManager } procedure TTestConfigManager.TestConfigLoading; var Config: TConfigManager; Value: string; begin Config := TConfigManager.Create('test_config.ini'); try Value := Config.GetString('Test', 'Key', 'Default'); CheckEquals('Default', Value); finally Config.Free; end; end; procedure TTestConfigManager.TestConfigSaving; var Config: TConfigManager; Value: string; begin Config := TConfigManager.Create('test_config.ini'); try Config.SetString('Test', 'Key', 'Value'); Config.Save; // 重新加载验证 Config.Load; Value := Config.GetString('Test', 'Key', 'Default'); CheckEquals('Value', Value); finally Config.Free; end; end; procedure TTestConfigManager.TestConfigTypes; var Config: TConfigManager; StrValue: string; IntValue: Integer; BoolValue: Boolean; FloatValue: Double; begin Config := TConfigManager.Create('test_config.ini'); try Config.SetString('Test', 'String', 'Hello'); Config.SetInteger('Test', 'Integer', 123); Config.SetBoolean('Test', 'Boolean', True); Config.SetFloat('Test', 'Float', 123.45); StrValue := Config.GetString('Test', 'String', 'Default'); IntValue := Config.GetInteger('Test', 'Integer', 0); BoolValue := Config.GetBoolean('Test', 'Boolean', False); FloatValue := Config.GetFloat('Test', 'Float', 0.0); CheckEquals('Hello', StrValue); CheckEquals(123, IntValue); CheckEquals(True, BoolValue); CheckEquals(123.45, FloatValue, 0.01); finally Config.Free; end; end; procedure TTestConfigManager.TestAppConfig; begin CheckNotNull(Config, 'App config should be created'); CheckNotNull(Config.GetServerURL, 'Server URL should be set'); Check(Config.GetServerPort > 0, 'Server port should be valid'); Check(Config.GetTimeout > 0, 'Timeout should be valid'); end; procedure TTestConfigManager.TestAppConfigExtended; begin CheckNotNull(Config.GetFileServerPath, 'File server path should be set'); CheckNotNull(Config.GetBackupServerPath, 'Backup server path should be set'); Check(Config.GetSyncInterval > 0, 'Sync interval should be valid'); Check(Config.GetMaxRetryCount > 0, 'Max retry count should be valid'); Check(Config.GetLogFileMaxSize > 0, 'Log file max size should be valid'); end; procedure TTestConfigManager.TestConfigArrayAndObject; var Config: TConfigManager; ArrayValue: TArray; begin Config := TConfigManager.Create('test_config.ini'); try SetLength(ArrayValue, 3); ArrayValue[0] := 'item1'; ArrayValue[1] := 'item2'; ArrayValue[2] := 'item3'; Config.SetArray('Test', 'Array', ArrayValue); ArrayValue := Config.GetArray('Test', 'Array', []); Check(Length(ArrayValue) = 3, 'Array should have 3 items'); CheckEquals('item1', ArrayValue[0]); CheckEquals('item2', ArrayValue[1]); CheckEquals('item3', ArrayValue[2]); finally Config.Free; end; end; { TTestBusinessServices } procedure TTestBusinessServices.TestAuthService; var AuthService: TAuthService; Result: TAuthResult; begin AuthService := TAuthService.Create; try Result := AuthService.Login('test', 'test'); Check(Result.Success, 'Login should succeed'); CheckNotNull(Result.Token, 'Token should be returned'); finally AuthService.Free; end; end; procedure TTestBusinessServices.TestWorkOrderService; var WorkOrderService: TWorkOrderService; Orders: TArray; begin WorkOrderService := TWorkOrderService.Create('test-token'); try Orders := WorkOrderService.GetWorkOrderList; Check(Length(Orders) >= 0, 'Work order list should be returned'); finally WorkOrderService.Free; end; end; procedure TTestBusinessServices.TestDeviceService; var DeviceService: TDeviceService; Status: TDeviceStatus; Devices: TArray; begin DeviceService := TDeviceService.Create; try Status := DeviceService.GetDeviceStatus('PLC-001'); Check(Status.DeviceID = 'PLC-001', 'Device status should be returned'); Devices := DeviceService.GetAllDevices; Check(Length(Devices) >= 0, 'Device list should be returned'); finally DeviceService.Free; end; end; procedure TTestBusinessServices.TestSyncService; var SyncService: TSyncService; Data: TJSONObject; Result: Boolean; begin SyncService := TSyncService.Create('test-token'); try Data := TJSONObject.Create; try Data.AddPair('test', 'value'); Result := SyncService.SyncData(Data); Check(Result, 'Sync should succeed'); finally Data.Free; end; finally SyncService.Free; end; end; procedure TTestBusinessServices.TestAuthServiceLogout; var AuthService: TAuthService; Result: Boolean; begin AuthService := TAuthService.Create; try Result := AuthService.Logout('test-token'); Check(Result, 'Logout should succeed'); finally AuthService.Free; end; end; procedure TTestBusinessServices.TestAuthServiceRefreshToken; var AuthService: TAuthService; NewToken: string; begin AuthService := TAuthService.Create; try NewToken := AuthService.RefreshToken('old-token'); CheckNotNull(NewToken, 'Refreshed token should be returned'); CheckNotSame('old-token', NewToken, 'Token should be different'); finally AuthService.Free; end; end; procedure TTestBusinessServices.TestWorkOrderServiceCreate; var WorkOrderService: TWorkOrderService; OrderInfo: TWorkOrderInfo; NewOrderID: string; begin WorkOrderService := TWorkOrderService.Create('test-token'); try OrderInfo.Clear; OrderInfo.OrderNumber := 'WO-NEW-001'; OrderInfo.MaterialID := 'MAT-001'; OrderInfo.MaterialName := 'Test Material'; OrderInfo.Quantity := 100; NewOrderID := WorkOrderService.CreateWorkOrder(OrderInfo); CheckNotNull(NewOrderID, 'New order ID should be returned'); finally WorkOrderService.Free; end; end; procedure TTestBusinessServices.TestWorkOrderServiceUpdateStatus; var WorkOrderService: TWorkOrderService; Result: Boolean; begin WorkOrderService := TWorkOrderService.Create('test-token'); try Result := WorkOrderService.UpdateWorkOrderStatus('WO-001', 'Completed'); Check(Result, 'Update status should succeed'); finally WorkOrderService.Free; end; end; procedure TTestBusinessServices.TestWorkOrderServiceReportProduction; var WorkOrderService: TWorkOrderService; Result: Boolean; begin WorkOrderService := TWorkOrderService.Create('test-token'); try Result := WorkOrderService.ReportProduction('WO-001', 'Process-001', '50'); Check(Result, 'Report production should succeed'); finally WorkOrderService.Free; end; end; procedure TTestBusinessServices.TestDeviceServiceConnectDisconnect; var DeviceService: TDeviceService; Result: Boolean; begin DeviceService := TDeviceService.Create; try Result := DeviceService.ConnectDevice('PLC-001'); Check(Result, 'Connect device should succeed'); Result := DeviceService.DisconnectDevice('PLC-001'); Check(Result, 'Disconnect device should succeed'); finally DeviceService.Free; end; end; procedure TTestBusinessServices.TestDeviceServiceSendCommand; var DeviceService: TDeviceService; Response: string; begin DeviceService := TDeviceService.Create; try Response := DeviceService.SendCommand('PLC-001', 'READ_D100'); CheckNotNull(Response, 'Command response should be returned'); Check(Response <> '', 'Command response should not be empty'); finally DeviceService.Free; end; end; procedure TTestBusinessServices.TestSyncServiceBatch; var SyncService: TSyncService; DataArray: TJSONArray; Result: Boolean; begin SyncService := TSyncService.Create('test-token'); try DataArray := TJSONArray.Create; try DataArray.AddElement(TJSONObject.Create.AddPair('key', 'value1')); DataArray.AddElement(TJSONObject.Create.AddPair('key', 'value2')); Result := SyncService.SyncBatchData(DataArray); Check(Result, 'Batch sync should succeed'); finally DataArray.Free; end; finally SyncService.Free; end; end; procedure TTestBusinessServices.TestSyncServiceRetry; var SyncService: TSyncService; RetryCount: Integer; begin SyncService := TSyncService.Create('test-token'); try RetryCount := SyncService.RetryFailedSyncs; Check(RetryCount >= 0, 'Retry count should be non-negative'); finally SyncService.Free; end; end; procedure TTestBusinessServices.TestProductionReportingService; var ProductionService: TProductionReportingService; Result: Boolean; begin ProductionService := TProductionReportingService.Create('test-token'); try Result := ProductionService.ReportProduction('WO-001', 'Process-001', '50', 'LOT-001'); Check(Result, 'Report production should succeed'); finally ProductionService.Free; end; end; procedure TTestBusinessServices.TestProductionReportingServiceValidateUser; var ProductionService: TProductionReportingService; Result: Boolean; begin ProductionService := TProductionReportingService.Create('test-token'); try Result := ProductionService.ValidateUser('test-user'); Check(Result, 'Validate user should succeed'); finally ProductionService.Free; end; end; procedure TTestBusinessServices.TestProductionReportingServiceGetWorkOrderInfo; var ProductionService: TProductionReportingService; WorkOrderInfo: TJSONObject; begin ProductionService := TProductionReportingService.Create('test-token'); try WorkOrderInfo := ProductionService.GetWorkOrderInfo('LOT-001'); CheckNotNull(WorkOrderInfo, 'Work order info should be returned'); CheckNotNull(WorkOrderInfo.GetValue('lotNo'), 'Lot number should be present'); finally ProductionService.Free; end; end; procedure TTestBusinessServices.TestProductionReportingServiceGetProcessList; var ProductionService: TProductionReportingService; ProcessList: TJSONArray; begin ProductionService := TProductionReportingService.Create('test-token'); try ProcessList := ProductionService.GetProcessList('LOT-001'); CheckNotNull(ProcessList, 'Process list should be returned'); Check(ProcessList.Count >= 0, 'Process list should have at least 0 items'); finally ProductionService.Free; end; end; procedure TTestBusinessServices.TestProductionReportingServiceValidateGoodsNo; var ProductionService: TProductionReportingService; Result: Boolean; begin ProductionService := TProductionReportingService.Create('test-token'); try Result := ProductionService.ValidateGoodsNo('ITEM-001', 'PROCESS-001', 'WO-001'); Check(Result, 'Validate goods no should succeed'); finally ProductionService.Free; end; end; procedure TTestBusinessServices.TestProductionReportingServiceSubmitData; var ProductionService: TProductionReportingService; Result: Boolean; begin ProductionService := TProductionReportingService.Create('test-token'); try Result := ProductionService.SubmitProductionData('test-user', 'LOT-001', '1', 'ITEM-001'); Check(Result, 'Submit production data should succeed'); finally ProductionService.Free; end; end; procedure TTestBusinessServices.TestDeviceConfigService; var DeviceConfigService: TDeviceConfigService; Result: Boolean; begin DeviceConfigService := TDeviceConfigService.Create; try Result := DeviceConfigService.LoadDeviceConfig; Check(Result, 'Load device config should succeed'); Result := DeviceConfigService.SaveDeviceConfig; Check(Result, 'Save device config should succeed'); finally DeviceConfigService.Free; end; end; procedure TTestBusinessServices.TestDataAccessService; var DataAccessService: TDataAccessService; Value: string; begin DataAccessService := TDataAccessService.Create; try Value := DataAccessService.ReadConfigValue('Test', 'Key', 'Default'); CheckEquals('Default', Value, 'Default value should be returned'); DataAccessService.WriteConfigValue('Test', 'Key', 'Value'); Value := DataAccessService.ReadConfigValue('Test', 'Key', 'Default'); CheckEquals('Value', Value, 'Written value should be returned'); finally DataAccessService.Free; end; end; { TTestCommonUtils } procedure TTestCommonUtils.TestValidator; begin Check(TValidator.IsEmpty(''), 'Empty string should be detected'); Check(not TValidator.IsEmpty('Test'), 'Non-empty string should not be detected as empty'); Check(TValidator.IsInteger('123'), 'Valid integer should be detected'); Check(not TValidator.IsInteger('abc'), 'Invalid integer should not be detected'); Check(TValidator.IsFloat('123.45'), 'Valid float should be detected'); Check(not TValidator.IsFloat('abc'), 'Invalid float should not be detected'); end; procedure TTestCommonUtils.TestStringHelper; var S: string; begin S := '123'; Check(S.IsInteger, 'String should be detected as integer'); S := '123.45'; Check(S.IsFloat, 'String should be detected as float'); S := 'Hello'; Check(S.Contains('ell'), 'String should contain substring'); Check(S.StartsWith('He'), 'String should start with prefix'); Check(S.EndsWith('lo'), 'String should end with suffix'); end; procedure TTestCommonUtils.TestDateTimeHelper; var DT: TDateTime; begin DT := Now; Check(TDateTimeHelper.IsToday(DT), 'Date should be today'); Check(TDateTimeHelper.IsSameDay(DT, DT), 'Date should be same day'); end; procedure TTestCommonUtils.TestFileHelper; var TempFile: string; Content: string; begin TempFile := TFileHelper.GetTempFileName('.txt'); try TFileHelper.WriteTextFile(TempFile, 'Test content'); Content := TFileHelper.ReadTextFile(TempFile); CheckEquals('Test content', Content, 'File content should match'); finally if FileExists(TempFile) then DeleteFile(TempFile); end; end; procedure TTestCommonUtils.TestJSONHelper; var JSON: TJSONObject; Value: string; IntValue: Integer; begin JSON := TJSONObject.Create; try JSON.AddPair('string', 'value'); JSON.AddPair('integer', TJSONNumber.Create(123)); Value := TJSONHelper.GetString(JSON, 'string', 'default'); CheckEquals('value', Value, 'String value should be retrieved'); IntValue := TJSONHelper.GetInteger(JSON, 'integer', 0); CheckEquals(123, IntValue, 'Integer value should be retrieved'); finally JSON.Free; end; end; initialization RegisterTest('ExceptionHandler', TTestExceptionHandler.Suite); RegisterTest('LogManager', TTestLogManager.Suite); RegisterTest('ConfigManager', TTestConfigManager.Suite); RegisterTest('BusinessServices', TTestBusinessServices.Suite); RegisterTest('CommonUtils', TTestCommonUtils.Suite); end.