test: 테스트 자동화 구현 및 Mock 서비스 오류 수정
- 테스트 패키지 추가 (mockito, golden_toolkit, patrol 등) - 테스트 가이드 문서 작성 (TEST_GUIDE.md) - 테스트 진행 상황 문서 작성 (TEST_PROGRESS.md) - 테스트 헬퍼 클래스 구현 - test_helpers.dart: 기본 테스트 유틸리티 - mock_data_helpers.dart: Mock 데이터 생성 헬퍼 - mock_services.dart: Mock 서비스 설정 (오류 수정 완료) - simple_mock_services.dart: 간단한 Mock 서비스 - 단위 테스트 구현 - CompanyListController 테스트 - EquipmentListController 테스트 - UserListController 테스트 - Widget 테스트 구현 (CompanyListScreen) Mock 서비스 주요 수정사항: - dartz import 추가 - Either 타입 제거 (실제 서비스와 일치하도록) - 메서드 시그니처 수정 (실제 서비스 인터페이스와 일치) - Mock 데이터 생성 메서드 추가 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
215
TEST_GUIDE.md
Normal file
215
TEST_GUIDE.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# Flutter 테스트 자동화 가이드
|
||||
|
||||
## 📋 개요
|
||||
이 문서는 Flutter 앱의 테스트 자동화를 위한 가이드입니다. 각 화면의 버튼 클릭, 서버 통신, 데이터 입력/수정/저장 등 모든 액션에 대한 테스트를 포함합니다.
|
||||
|
||||
## 🏗️ 테스트 구조
|
||||
|
||||
```
|
||||
test/
|
||||
├── helpers/ # 테스트 헬퍼 클래스
|
||||
│ ├── test_helpers.dart # 기본 테스트 헬퍼
|
||||
│ ├── mock_data_helpers.dart # Mock 데이터 생성 헬퍼
|
||||
│ └── simple_mock_services.dart # Mock 서비스 설정
|
||||
├── unit/ # 단위 테스트
|
||||
│ └── controllers/ # 컨트롤러 테스트
|
||||
├── widget/ # Widget 테스트
|
||||
│ └── screens/ # 화면별 Widget 테스트
|
||||
└── integration/ # 통합 테스트
|
||||
```
|
||||
|
||||
## 🔧 테스트 환경 설정
|
||||
|
||||
### 1. 필요한 패키지 (pubspec.yaml)
|
||||
```yaml
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
integration_test:
|
||||
sdk: flutter
|
||||
mockito: ^5.4.5
|
||||
build_runner: ^2.4.9
|
||||
golden_toolkit: ^0.15.0
|
||||
mocktail: ^1.0.3
|
||||
fake_async: ^1.3.1
|
||||
test: ^1.25.2
|
||||
coverage: ^1.7.2
|
||||
patrol: ^3.6.0
|
||||
```
|
||||
|
||||
### 2. Mock 클래스 생성
|
||||
```bash
|
||||
flutter pub run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
## 📝 테스트 작성 예제
|
||||
|
||||
### 1. 컨트롤러 단위 테스트
|
||||
```dart
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
void main() {
|
||||
late CompanyListController controller;
|
||||
late MockMockDataService mockDataService;
|
||||
late MockCompanyService mockCompanyService;
|
||||
late GetIt getIt;
|
||||
|
||||
setUp(() {
|
||||
getIt = setupTestGetIt();
|
||||
mockDataService = MockMockDataService();
|
||||
mockCompanyService = MockCompanyService();
|
||||
|
||||
// GetIt에 서비스 등록
|
||||
getIt.registerSingleton<CompanyService>(mockCompanyService);
|
||||
|
||||
// Mock 설정
|
||||
SimpleMockServiceHelpers.setupMockDataServiceMock(mockDataService);
|
||||
SimpleMockServiceHelpers.setupCompanyServiceMock(mockCompanyService);
|
||||
|
||||
controller = CompanyListController(dataService: mockDataService);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
controller.dispose();
|
||||
getIt.reset();
|
||||
});
|
||||
|
||||
group('CompanyListController 테스트', () {
|
||||
test('검색 기능 테스트', () async {
|
||||
await controller.updateSearchKeyword('테스트');
|
||||
expect(controller.searchKeyword, '테스트');
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Widget 테스트
|
||||
```dart
|
||||
testWidgets('화면 렌더링 테스트', (WidgetTester tester) async {
|
||||
await pumpTestWidget(
|
||||
tester,
|
||||
const CompanyListRedesign(),
|
||||
);
|
||||
|
||||
await pumpAndSettleWithTimeout(tester);
|
||||
|
||||
expect(find.text('회사 관리'), findsOneWidget);
|
||||
expect(find.byType(TextField), findsOneWidget);
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Mock 데이터 생성
|
||||
```dart
|
||||
// 회사 목록 생성
|
||||
final companies = MockDataHelpers.createMockCompanyList(count: 5);
|
||||
|
||||
// 특정 회사 생성
|
||||
final company = MockDataHelpers.createMockCompany(
|
||||
id: 1,
|
||||
name: '테스트 회사',
|
||||
);
|
||||
```
|
||||
|
||||
## 🎯 테스트 전략
|
||||
|
||||
### 1. 단위 테스트 (Unit Tests)
|
||||
- **대상**: 컨트롤러, 서비스, 유틸리티 함수
|
||||
- **목적**: 개별 컴포넌트의 로직 검증
|
||||
- **실행**: `flutter test test/unit/`
|
||||
|
||||
### 2. Widget 테스트
|
||||
- **대상**: 개별 화면 및 위젯
|
||||
- **목적**: UI 렌더링 및 상호작용 검증
|
||||
- **실행**: `flutter test test/widget/`
|
||||
|
||||
### 3. 통합 테스트 (Integration Tests)
|
||||
- **대상**: 전체 사용자 플로우
|
||||
- **목적**: 실제 앱 동작 검증
|
||||
- **실행**: `flutter test integration_test/`
|
||||
|
||||
## 🔍 주요 테스트 케이스
|
||||
|
||||
### 화면별 필수 테스트
|
||||
1. **초기 렌더링**: 화면이 올바르게 표시되는지 확인
|
||||
2. **데이터 로딩**: API 호출 및 데이터 표시 확인
|
||||
3. **사용자 입력**: 텍스트 입력, 버튼 클릭 등
|
||||
4. **네비게이션**: 화면 전환 동작 확인
|
||||
5. **에러 처리**: 네트워크 오류, 유효성 검사 실패 등
|
||||
6. **상태 관리**: 로딩, 성공, 실패 상태 전환
|
||||
|
||||
## 🚨 주의사항
|
||||
|
||||
### 1. 모델 불일치 문제
|
||||
- 실제 모델과 Mock 모델의 구조가 일치하는지 확인
|
||||
- 특히 `Address`, `Company`, `User` 모델 주의
|
||||
|
||||
### 2. 서비스 시그니처
|
||||
- Mock 서비스의 메서드 시그니처가 실제 서비스와 일치해야 함
|
||||
- 반환 타입 특히 주의 (예: `User` vs `AuthUser`)
|
||||
|
||||
### 3. GetIt 설정
|
||||
- 테스트 전 반드시 GetIt 초기화
|
||||
- 테스트 후 반드시 GetIt reset
|
||||
|
||||
## 📊 테스트 커버리지
|
||||
|
||||
### 커버리지 확인
|
||||
```bash
|
||||
flutter test --coverage
|
||||
genhtml coverage/lcov.info -o coverage/html
|
||||
open coverage/html/index.html
|
||||
```
|
||||
|
||||
### 목표 커버리지
|
||||
- 단위 테스트: 80% 이상
|
||||
- Widget 테스트: 70% 이상
|
||||
- 통합 테스트: 주요 사용자 시나리오 100%
|
||||
|
||||
## 🔄 CI/CD 통합
|
||||
|
||||
### GitHub Actions 예제
|
||||
```yaml
|
||||
name: Test
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: subosito/flutter-action@v2
|
||||
- run: flutter pub get
|
||||
- run: flutter test
|
||||
- run: flutter test --coverage
|
||||
```
|
||||
|
||||
## 📚 추가 리소스
|
||||
- [Flutter Testing Documentation](https://flutter.dev/docs/testing)
|
||||
- [Mockito Documentation](https://pub.dev/packages/mockito)
|
||||
- [GetIt Documentation](https://pub.dev/packages/get_it)
|
||||
|
||||
## 🔧 문제 해결
|
||||
|
||||
### Mock 클래스를 찾을 수 없을 때
|
||||
```bash
|
||||
flutter pub run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
### 테스트가 타임아웃될 때
|
||||
`pumpAndSettleWithTimeout` 헬퍼 사용:
|
||||
```dart
|
||||
await pumpAndSettleWithTimeout(tester, timeout: Duration(seconds: 10));
|
||||
```
|
||||
|
||||
### GetIt 관련 오류
|
||||
```dart
|
||||
setUp(() {
|
||||
getIt = setupTestGetIt(); // 반드시 첫 번째로 실행
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
getIt.reset(); // 반드시 실행
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user