Line data Source code
1 : import 'dart:io';
2 : import 'package:flutter/foundation.dart';
3 : import 'package:yaml/yaml.dart';
4 : import 'package:path/path.dart' as path;
5 :
6 : /// CI/CD 환경과 로컬 환경에서 테스트 실행 시 설정을 관리하는 클래스
7 : class TestConfig {
8 : static TestConfig? _instance;
9 :
10 : // 기본 설정값
11 : int asyncTimeout = 800;
12 : int testDelay = 100;
13 : int retryCount = 1;
14 : bool parallel = true;
15 : int memoryLimit = 0; // 0은 제한 없음
16 : int logLevel = 2;
17 : String isolationMode = 'normal';
18 : int timerCompletionWait = 500; // 테스트 종료 전 타이머 완료 대기 시간
19 : bool isCI = false;
20 :
21 : /// 싱글톤 인스턴스 반환
22 12 : static TestConfig get instance {
23 12 : _instance ??= TestConfig._internal();
24 : return _instance!;
25 : }
26 :
27 12 : TestConfig._internal() {
28 12 : _loadConfig();
29 : }
30 :
31 : /// 설정 파일 로드
32 12 : void _loadConfig() {
33 : try {
34 : // CI 환경 감지
35 36 : isCI = Platform.environment.containsKey('CI') ||
36 24 : Platform.environment.containsKey('GITHUB_ACTIONS') ||
37 24 : Platform.environment.containsKey('GITLAB_CI');
38 :
39 : if (kDebugMode) {
40 36 : print('TestConfig: CI 환경 감지 - $isCI');
41 : }
42 :
43 : // 설정 파일 경로
44 12 : final configPath = isCI
45 : ? '.github/workflows/test_config.yaml'
46 : : 'test/test_config.yaml';
47 :
48 : // 프로젝트 루트 디렉토리 찾기
49 24 : String projectRoot = Directory.current.path;
50 :
51 : // pubspec.yaml이 있는 디렉토리를 찾을 때까지 상위 디렉토리로 이동
52 36 : while (!File(path.join(projectRoot, 'pubspec.yaml')).existsSync()) {
53 0 : final parent = Directory(projectRoot).parent;
54 0 : if (parent.path == projectRoot) {
55 : // 루트에 도달했는데도 pubspec.yaml을 찾지 못함
56 : break;
57 : }
58 0 : projectRoot = parent.path;
59 : }
60 :
61 24 : final configFile = File(path.join(projectRoot, configPath));
62 :
63 12 : if (configFile.existsSync()) {
64 12 : final yamlString = configFile.readAsStringSync();
65 12 : final yamlMap = loadYaml(yamlString) as Map;
66 :
67 12 : if (yamlMap.containsKey('test_settings')) {
68 0 : final settings = yamlMap['test_settings'] as Map;
69 :
70 0 : asyncTimeout = settings['async_timeout'] ?? asyncTimeout;
71 0 : testDelay = settings['test_delay'] ?? testDelay;
72 0 : retryCount = settings['retry_count'] ?? retryCount;
73 0 : parallel = settings['parallel'] ?? parallel;
74 0 : memoryLimit = settings['memory_limit'] ?? memoryLimit;
75 0 : logLevel = settings['log_level'] ?? logLevel;
76 0 : isolationMode = settings['isolation_mode'] ?? isolationMode;
77 0 : timerCompletionWait = settings['timer_completion_wait'] ?? timerCompletionWait;
78 :
79 : if (kDebugMode) {
80 0 : print('TestConfig: 설정 파일 로드 성공 - $configPath');
81 0 : print('TestConfig: asyncTimeout=$asyncTimeout, testDelay=$testDelay, retryCount=$retryCount');
82 : }
83 : }
84 : } else {
85 : if (kDebugMode) {
86 0 : print('TestConfig: 설정 파일 없음 - $configPath, 기본값 사용');
87 : }
88 : }
89 : } catch (e) {
90 : if (kDebugMode) {
91 0 : print('TestConfig: 설정 로드 중 오류 - $e');
92 : }
93 : }
94 : }
95 :
96 : /// 테스트 환경에 맞는 비동기 타임아웃 값 반환
97 0 : Duration get asyncTimeoutDuration => Duration(milliseconds: asyncTimeout);
98 :
99 : /// 테스트 환경에 맞는 테스트 간 지연 시간 반환
100 0 : Duration get testDelayDuration => Duration(milliseconds: testDelay);
101 :
102 : /// 테스트 종료 전 타이머 완료 대기 시간 반환
103 0 : Duration get timerCompletionWaitDuration => Duration(milliseconds: timerCompletionWait);
104 :
105 : /// 테스트 환경에 맞는 로그 레벨 반환 (디버깅 상세도)
106 36 : bool get isVerboseLogging => logLevel >= 4;
107 :
108 : /// 테스트 격리 모드가 strict인지 확인
109 0 : bool get isStrictIsolation => isolationMode == 'strict';
110 : }
|