# 테스트 문제 해결 가이드

## 목차
1. [소개](#소개)
2. [일반적인 테스트 실패 원인](#일반적인-테스트-실패-원인)
3. [EventBus 관련 문제](#eventbus-관련-문제)
4. [비동기 테스트 문제](#비동기-테스트-문제)
5. [메모리 및 리소스 관리 문제](#메모리-및-리소스-관리-문제)
6. [CI 환경 특화 문제](#ci-환경-특화-문제)
7. [문제 해결 도구](#문제-해결-도구)
8. [테스트 실행 가이드](#테스트-실행-가이드)

## 소개

이 문서는 볼링 매니저 앱의 테스트 실행 중 발생할 수 있는 다양한 문제와 그 해결 방법을 설명합니다. 특히 EventBus와 MemberService 테스트의 신뢰성 문제에 초점을 맞추고 있습니다.

## 일반적인 테스트 실패 원인

### 1. 테스트 간 상태 격리 실패

**증상:**
- 테스트를 개별적으로 실행하면 통과하지만, 전체 테스트를 실행하면 실패
- 테스트 실행 순서에 따라 결과가 달라짐

**원인:**
- 테스트 간 공유 상태(싱글톤, 정적 변수 등)가 적절히 초기화되지 않음
- 테스트 종료 후 리소스가 제대로 정리되지 않음

**해결 방법:**
- `setUp`과 `tearDown`에서 모든 공유 상태 초기화
- 싱글톤 인스턴스를 테스트마다 재설정
- `TestUtils.isInTest` 플래그를 활용하여 테스트 환경에서 특별한 처리 적용
- 격리 모드를 `strict`로 설정하여 테스트 간 상태 공유 최소화

### 2. 타이밍 및 비동기 문제

**증상:**
- 간헐적인 테스트 실패
- `Timeout` 오류 발생
- 비동기 작업 완료 전에 테스트가 종료됨

**원인:**
- 고정된 지연 시간(`Future.delayed`)에 의존
- 비동기 작업 완료를 적절히 기다리지 않음
- 테스트 환경(CI vs 로컬)에 따른 실행 속도 차이

**해결 방법:**
- 고정 지연 대신 `TestConfig`에서 환경별 설정 사용
- `expectLater`와 `completes` 매처 활용
- 비동기 작업 완료를 명시적으로 기다리는 코드 추가

## EventBus 관련 문제

### 1. 구독 해제 문제

**증상:**
- `EventBus: 구독 취소됨` 로그가 누락됨
- 활성 구독 수(`_activeSubscriptionCount`)가 감소하지 않음
- 테스트 간 이벤트 간섭 발생

**원인:**
- `dispose()` 메서드에서 구독 취소가 제대로 이루어지지 않음
- 구독 취소 전에 테스트가 종료됨
- 구독 카운터 관리 버그

**해결 방법:**
- `dispose()` 메서드에서 모든 구독을 명시적으로 취소
- `tearDown`에서 `EventBus.resetAllTestInstances()` 호출
- 테스트 ID를 사용하여 테스트별 EventBus 인스턴스 격리

### 2. 이벤트 전달 문제

**증상:**
- 이벤트가 발생했지만 구독자에게 전달되지 않음
- 테스트에서 이벤트 처리 검증 실패

**원인:**
- 이벤트 발생과 처리 사이의 비동기 타이밍 문제
- 잘못된 테스트 ID로 인한 이벤트 격리
- 이벤트 구독 전에 이벤트가 발생함

**해결 방법:**
- 이벤트 발생 후 적절한 지연 추가 (환경 설정 기반)
- 테스트 ID 설정 확인
- 이벤트 발생 전에 구독이 완료되었는지 확인

## 비동기 테스트 문제

### 1. 타임아웃 문제

**증상:**
- `Test timed out after X milliseconds` 오류
- CI 환경에서 더 자주 발생

**원인:**
- 테스트 타임아웃 값이 너무 짧음
- 비동기 작업이 예상보다 오래 걸림
- 리소스 경합으로 인한 지연

**해결 방법:**
- `TestConfig`를 통해 환경별 타임아웃 값 조정
- 비동기 작업 완료를 명시적으로 기다림
- CI 환경에서 더 긴 타임아웃 설정

### 2. 비동기 작업 완료 대기 문제

**증상:**
- 비동기 작업 결과를 검증하기 전에 테스트가 종료됨
- 간헐적인 테스트 실패

**원인:**
- `await`가 누락됨
- 잘못된 비동기 패턴 사용
- 이벤트 루프 블로킹

**해결 방법:**
- 모든 비동기 작업에 `await` 사용
- `expectLater`와 함께 `completes` 또는 `completion` 매처 사용
- `pumpAndSettle`을 사용하여 모든 마이크로태스크가 완료될 때까지 대기

## 메모리 및 리소스 관리 문제

### 1. 리소스 누수

**증상:**
- 메모리 사용량 증가
- 테스트 실행이 느려짐
- 장시간 테스트 실행 시 실패 증가

**원인:**
- `dispose()` 메서드에서 리소스 정리 누락
- 구독, 스트림, 컨트롤러 등이 제대로 닫히지 않음
- 테스트 간 공유 리소스가 정리되지 않음

**해결 방법:**
- 모든 서비스 클래스에 철저한 `dispose()` 구현
- `tearDown`에서 모든 리소스 정리
- 메모리 누수 감지 도구 활용

### 2. 구독 관리 문제

**증상:**
- `EventBus` 활성 구독 수가 계속 증가
- 이벤트가 예상보다 많은 구독자에게 전달됨

**원인:**
- 구독 취소가 제대로 이루어지지 않음
- 구독 카운터 관리 버그
- 테스트 간 구독 객체 공유

**해결 방법:**
- 모든 구독을 변수에 저장하고 명시적으로 취소
- `StreamSubscription` 객체 관리 개선
- 테스트 ID 기반 구독 격리

## CI 환경 특화 문제

### 1. 환경 차이로 인한 문제

**증상:**
- 로컬에서는 통과하지만 CI에서는 실패하는 테스트
- CI에서 더 느린 테스트 실행 속도
- 리소스 제약으로 인한 타임아웃

**원인:**
- CI 환경의 제한된 리소스 (CPU, 메모리)
- 환경별 설정 차이
- 병렬 실행으로 인한 리소스 경합

**해결 방법:**
- 환경 감지 및 설정 자동 조정 (`TestConfig` 활용)
- CI 환경에서 더 긴 타임아웃 및 지연 설정
- 필요시 CI에서 순차 실행 적용

### 2. 로깅 및 디버깅 문제

**증상:**
- CI에서 테스트 실패 원인 파악이 어려움
- 로그 정보 부족

**원인:**
- CI 환경에서 제한된 로그 출력
- 디버깅 정보 부족

**해결 방법:**
- CI 환경에서 상세 로깅 활성화
- `TestDiagnostics` 유틸리티를 통한 자동 진단 정보 수집
- 실패 시 시스템 정보 수집 및 저장

## 문제 해결 도구

### 1. 테스트 진단 유틸리티

`TestDiagnostics` 클래스는 테스트 실패 시 자동으로 진단 정보를 수집하고 분석합니다:

```dart
// 테스트 실패 기록
TestDiagnostics.instance.recordFailure(
  '테스트 이름',
  '오류 메시지',
  stackTrace: stackTrace
);

// 테스트 종료 시 요약 생성
await TestDiagnostics.instance.generateSummary();
```

### 2. 테스트 재현 스크립트

테스트 실패를 재현하고 진단하기 위한 스크립트:

```bash
# 특정 테스트 재현
./scripts/reproduce_test.sh "MemberService 테스트" --verbose

# 환경별 테스트 실행
./scripts/run_tests.sh ci --pattern="EventBus" --timeout=3000
```

### 3. 테스트 설정 관리

환경별 테스트 설정을 관리하기 위한 `TestConfig` 클래스:

```dart
// 환경별 설정 사용
final timeout = TestConfig.instance.asyncTimeout;
final delay = TestConfig.instance.testDelayDuration;

// 비동기 작업 대기
await Future.delayed(delay);
```

## 테스트 실행 가이드

### 로컬 환경에서 테스트 실행

```bash
# 전체 테스트 실행
./scripts/run_tests.sh local

# 특정 테스트만 실행
./scripts/run_tests.sh local --pattern="MemberService"

# 상세 로그와 함께 실행
./scripts/run_tests.sh local --verbose
```

### CI 환경에서 테스트 실행

```bash
# CI 환경 설정으로 테스트 실행
./scripts/run_tests.sh ci

# 순차 실행 (병렬 실행 비활성화)
./scripts/run_tests.sh ci --sequential

# 타임아웃 증가
./scripts/run_tests.sh ci --timeout=5000
```

### 테스트 실패 분석

```bash
# 실패한 테스트 재현
./scripts/reproduce_test.sh "실패한 테스트 이름"

# 진단 정보 수집
./scripts/reproduce_test.sh "실패한 테스트 이름" --verbose
```

테스트 진단 로그는 `test_diagnostics` 디렉토리에 저장되며, 실패 분석 및 재현 스크립트도 이 디렉토리에 생성됩니다.
