- 모든 서비스 메서드 시그니처를 실제 구현에 맞게 수정 - TestDataGenerator 제거하고 직접 객체 생성으로 변경 - 모델 필드명 및 타입 불일치 수정 - 불필요한 Either 패턴 사용 제거 - null safety 관련 이슈 해결 수정된 파일: - test/integration/screens/company_integration_test.dart - test/integration/screens/equipment_integration_test.dart - test/integration/screens/user_integration_test.dart - test/integration/screens/login_integration_test.dart
11 KiB
11 KiB
Real API 기반 자동화 테스트 프레임워크 아키텍처
1. 개요
Real API 기반 자동화 테스트 프레임워크는 실제 API와 통신하며 화면별 기능을 자동으로 감지하고 테스트하는 고급 테스트 시스템입니다. 이 프레임워크는 API 에러 진단, 자동 수정, 테스트 데이터 생성 등의 기능을 포함합니다.
2. 아키텍처 개요
graph TB
subgraph "Test Runner Layer"
TR[Test Runner]
TO[Test Orchestrator]
end
subgraph "Framework Core"
STF[ScreenTestFramework]
AED[ApiErrorDiagnostics]
AF[AutoFixer]
TDG[TestDataGenerator]
end
subgraph "Infrastructure Layer"
TC[TestContext]
DC[DependencyContainer]
RC[ReportCollector]
end
subgraph "Screen Test Layer"
BST[BaseScreenTest]
LST[LicenseScreenTest]
EST[EquipmentScreenTest]
WST[WarehouseScreenTest]
end
subgraph "Support Layer"
RH[RetryHandler]
VM[ValidationManager]
DM[DiagnosticsManager]
end
TR --> TO
TO --> STF
STF --> BST
BST --> LST
BST --> EST
BST --> WST
STF --> AED
STF --> AF
STF --> TDG
AED --> DM
AF --> RH
TDG --> VM
STF --> TC
TC --> DC
STF --> RC
3. 핵심 컴포넌트 설계
3.1 ScreenTestFramework
abstract class ScreenTestFramework {
// 화면 기능 자동 감지
Future<List<TestableFeature>> detectFeatures(ScreenMetadata metadata);
// 테스트 실행
Future<TestResult> executeTests(List<TestableFeature> features);
// 에러 처리
Future<void> handleError(TestError error);
// 리포트 생성
Future<TestReport> generateReport();
}
class ScreenMetadata {
final String screenName;
final Type controllerType;
final List<ApiEndpoint> relatedEndpoints;
final Map<String, dynamic> screenCapabilities;
}
class TestableFeature {
final String featureName;
final FeatureType type;
final List<TestCase> testCases;
final Map<String, dynamic> metadata;
}
3.2 ApiErrorDiagnostics
abstract class ApiErrorDiagnostics {
// 에러 분석
Future<ErrorDiagnosis> diagnose(ApiError error);
// 근본 원인 분석
Future<RootCause> analyzeRootCause(ErrorDiagnosis diagnosis);
// 수정 제안
Future<List<FixSuggestion>> suggestFixes(RootCause rootCause);
// 패턴 학습
Future<void> learnFromError(ApiError error, FixResult result);
}
class ErrorDiagnosis {
final ErrorType type;
final String description;
final Map<String, dynamic> context;
final double confidence;
final List<String> affectedEndpoints;
}
class RootCause {
final String cause;
final CauseCategory category;
final List<Evidence> evidence;
final Map<String, dynamic> details;
}
3.3 AutoFixer
abstract class AutoFixer {
// 자동 수정 시도
Future<FixResult> attemptFix(FixSuggestion suggestion);
// 수정 검증
Future<bool> validateFix(FixResult result);
// 롤백
Future<void> rollback(FixResult result);
// 수정 이력 관리
Future<void> recordFix(FixResult result);
}
class FixSuggestion {
final String fixId;
final FixType type;
final String description;
final List<FixAction> actions;
final double successProbability;
}
class FixResult {
final bool success;
final String fixId;
final List<Change> changes;
final Duration duration;
final Map<String, dynamic> metrics;
}
3.4 TestDataGenerator
abstract class TestDataGenerator {
// 데이터 생성 전략
Future<GenerationStrategy> determineStrategy(DataRequirement requirement);
// 데이터 생성
Future<TestData> generate(GenerationStrategy strategy);
// 데이터 검증
Future<bool> validate(TestData data);
// 관계 데이터 생성
Future<Map<String, TestData>> generateRelated(DataRelationship relationship);
}
class DataRequirement {
final Type dataType;
final Map<String, FieldConstraint> constraints;
final List<DataRelationship> relationships;
final int quantity;
}
class TestData {
final String id;
final Type type;
final Map<String, dynamic> data;
final DateTime createdAt;
final List<String> relatedIds;
}
4. 상호작용 패턴
4.1 테스트 실행 시퀀스
sequenceDiagram
participant TR as Test Runner
participant STF as ScreenTestFramework
participant TDG as TestDataGenerator
participant BST as BaseScreenTest
participant AED as ApiErrorDiagnostics
participant AF as AutoFixer
participant RC as ReportCollector
TR->>STF: initializeTest(screenName)
STF->>STF: detectFeatures()
STF->>TDG: generateTestData()
TDG-->>STF: testData
STF->>BST: executeScreenTest(features, data)
BST->>BST: runTestCases()
alt Test Success
BST-->>STF: TestResult(success)
STF->>RC: collectResult()
else Test Failure
BST-->>STF: TestError
STF->>AED: diagnose(error)
AED-->>STF: ErrorDiagnosis
STF->>AF: attemptFix(diagnosis)
AF-->>STF: FixResult
alt Fix Success
STF->>BST: retryTest()
else Fix Failed
STF->>RC: recordFailure()
end
end
STF->>RC: generateReport()
RC-->>TR: TestReport
4.2 에러 진단 및 자동 수정 플로우
flowchart TD
A[API Error Detected] --> B{Error Type?}
B -->|Authentication| C[Auth Diagnostics]
B -->|Data Validation| D[Validation Diagnostics]
B -->|Network| E[Network Diagnostics]
B -->|Server Error| F[Server Diagnostics]
C --> G[Analyze Token Status]
D --> H[Check Data Format]
E --> I[Test Connectivity]
F --> J[Check Server Health]
G --> K{Token Valid?}
K -->|No| L[Refresh Token]
K -->|Yes| M[Check Permissions]
H --> N{Data Valid?}
N -->|No| O[Generate Valid Data]
N -->|Yes| P[Check Constraints]
L --> Q[Retry Request]
O --> Q
M --> Q
P --> Q
Q --> R{Success?}
R -->|Yes| S[Continue Test]
R -->|No| T[Record Failure]
5. 디렉토리 구조
test/integration/automated/
├── framework/
│ ├── core/
│ │ ├── screen_test_framework.dart
│ │ ├── api_error_diagnostics.dart
│ │ ├── auto_fixer.dart
│ │ └── test_data_generator.dart
│ ├── infrastructure/
│ │ ├── test_context.dart
│ │ ├── dependency_container.dart
│ │ └── report_collector.dart
│ ├── support/
│ │ ├── retry_handler.dart
│ │ ├── validation_manager.dart
│ │ └── diagnostics_manager.dart
│ └── models/
│ ├── test_models.dart
│ ├── error_models.dart
│ └── report_models.dart
├── screens/
│ ├── base/
│ │ └── base_screen_test.dart
│ ├── license/
│ │ ├── license_screen_test.dart
│ │ └── license_test_scenarios.dart
│ ├── equipment/
│ │ ├── equipment_screen_test.dart
│ │ └── equipment_test_scenarios.dart
│ └── warehouse/
│ ├── warehouse_screen_test.dart
│ └── warehouse_test_scenarios.dart
└── reports/
├── generators/
│ ├── html_report_generator.dart
│ └── json_report_generator.dart
└── templates/
└── report_template.html
6. 확장 가능한 구조
6.1 플러그인 시스템
abstract class TestPlugin {
String get name;
String get version;
Future<void> initialize(TestContext context);
Future<void> beforeTest(TestCase testCase);
Future<void> afterTest(TestResult result);
Future<void> onError(TestError error);
}
class PluginManager {
final List<TestPlugin> _plugins = [];
void register(TestPlugin plugin) {
_plugins.add(plugin);
}
Future<void> executePlugins(PluginPhase phase, dynamic data) async {
for (final plugin in _plugins) {
await plugin.execute(phase, data);
}
}
}
6.2 커스텀 진단 룰
abstract class DiagnosticRule {
String get ruleId;
int get priority;
bool canHandle(ApiError error);
Future<ErrorDiagnosis> diagnose(ApiError error);
}
class DiagnosticRuleEngine {
final List<DiagnosticRule> _rules = [];
void addRule(DiagnosticRule rule) {
_rules.add(rule);
_rules.sort((a, b) => b.priority.compareTo(a.priority));
}
Future<ErrorDiagnosis> diagnose(ApiError error) async {
for (final rule in _rules) {
if (rule.canHandle(error)) {
return await rule.diagnose(error);
}
}
return DefaultDiagnosis(error);
}
}
7. SOLID 원칙 적용
7.1 Single Responsibility Principle (SRP)
- 각 클래스는 하나의 책임만 가짐
- ScreenTestFramework: 화면 테스트 조정
- ApiErrorDiagnostics: 에러 진단
- AutoFixer: 에러 수정
- TestDataGenerator: 데이터 생성
7.2 Open/Closed Principle (OCP)
- 플러그인 시스템을 통한 확장
- 추상 클래스를 통한 구현 확장
- 새로운 화면 테스트 추가 시 기존 코드 수정 불필요
7.3 Liskov Substitution Principle (LSP)
- 모든 화면 테스트는 BaseScreenTest를 대체 가능
- 모든 진단 룰은 DiagnosticRule 인터페이스 준수
7.4 Interface Segregation Principle (ISP)
- 작고 구체적인 인터페이스 제공
- 클라이언트가 필요하지 않은 메서드에 의존하지 않음
7.5 Dependency Inversion Principle (DIP)
- 추상화에 의존, 구체적인 구현에 의존하지 않음
- DI 컨테이너를 통한 의존성 주입
8. 성능 및 확장성 고려사항
8.1 병렬 처리
class ParallelTestExecutor {
Future<List<TestResult>> executeParallel(
List<TestCase> testCases,
{int maxConcurrency = 4}
) async {
final pool = Pool(maxConcurrency);
final results = <TestResult>[];
await Future.wait(
testCases.map((testCase) =>
pool.withResource(() => executeTest(testCase))
)
);
return results;
}
}
8.2 캐싱 전략
class TestDataCache {
final Duration _ttl = Duration(minutes: 30);
final Map<String, CachedData> _cache = {};
Future<TestData> getOrGenerate(
String key,
Future<TestData> Function() generator
) async {
final cached = _cache[key];
if (cached != null && !cached.isExpired) {
return cached.data;
}
final data = await generator();
_cache[key] = CachedData(data, DateTime.now());
return data;
}
}
9. 모니터링 및 로깅
class TestMonitor {
final MetricsCollector _metrics;
final Logger _logger;
Future<void> monitorTest(TestCase testCase) async {
final stopwatch = Stopwatch()..start();
try {
await testCase.execute();
_metrics.recordSuccess(testCase.name, stopwatch.elapsed);
} catch (e) {
_metrics.recordFailure(testCase.name, stopwatch.elapsed);
_logger.error('Test failed: ${testCase.name}', e);
}
}
}
10. 결론
이 아키텍처는 확장 가능하고 유지보수가 용이한 Real API 기반 자동화 테스트 프레임워크를 제공합니다. SOLID 원칙을 준수하며, 플러그인 시스템을 통해 쉽게 확장할 수 있고, 에러 진단 및 자동 수정 기능을 통해 테스트의 안정성을 높입니다.