티스토리 뷰

반응형

이 가이드는 Flutter 앱에서 통합 테스트를 실행하는 방법을 설명합니다. 이를 통해 다음을 수행하는 방법을 배울 수 있습니다:

통합 테스트 설정하기

  • 앱이 특정 텍스트를 표시하는지 확인하기
  • 특정 위젯을 탭하기
  • 통합 테스트 실행하기

 

이 가이드에서는 Flutter에 포함된 counter_app 프로젝트와 Flutter의 integration_test 패키지를 참조합니다.

integration_test 패키지를 사용하면 다음과 같은 작업이 가능합니다:

  • flutter drive 명령어를 사용해 실제 기기나 에뮬레이터에서 테스트 실행하기
  • 다양한 기기에서 자동 테스트를 실행하기 위해 Firebase Test Lab에서 실행하기
  • flutter_test API를 사용하여 위젯 테스트와 유사한 스타일로 테스트 작성하기

 

테스트할 새 앱 만들기

통합 테스트를 위해서는 테스트할 앱이 필요합니다.

이 예제에서는 flutter create 명령어로 생성되는 기본 Counter App 예제를 사용합니다.

카운터 앱은 사용자가 버튼을 눌러 카운터 값을 증가시킬 수 있도록 합니다.

 

1. 기본 Flutter 앱을 생성하려면 터미널에서 다음 명령어를 실행하세요:

flutter create counter_app


2. counter_app 디렉터리로 이동합니다.

3. 선호하는 IDE에서 lib/main.dart 파일을 엽니다.

4. floatingActionButton() 위젯에 Key 클래스를 사용해 "increment"라는 문자열 값을 갖는 key 파라미터를 추가합니다:

 floatingActionButton: FloatingActionButton(
   key: const ValueKey('increment'),
   onPressed: _incrementCounter,
   tooltip: 'Increment',
   child: const Icon(Icons.add),
 ),

 

5. lib/main.dart 파일을 저장합니다.

 

위와 같이 수정한 후, lib/main.dart 파일은 다음과 같아야 합니다:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Counter App',
      home: MyHomePage(title: 'Counter App Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        // 이 버튼에 Key를 지정하세요.  
        // 이렇게 하면 테스트 코드에서 이 버튼을 찾고 탭할 수 있습니다.
        key: const Key('increment'),
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

 

integration_test 의존성 추가하기

새 앱에서 테스트 패키지를 사용하려면 다음을 추가해야 합니다:

 

아래 명령어를 실행하면 integration_test와 flutter_test 패키지를 sdk: flutter로 dev_dependencies에 추가할 수 있습니다:

flutter pub add 'dev:integration_test:{"sdk":"flutter"}'

 

출력 예시:

Building flutter tool...
Resolving dependencies... 
Got dependencies.
Resolving dependencies... 
+ file 7.0.0
+ flutter_driver 0.0.0 from sdk flutter
+ fuchsia_remote_debug_protocol 0.0.0 from sdk flutter
+ integration_test 0.0.0 from sdk flutter
...
  test_api 0.6.1 (0.7.1 available)
  vm_service 13.0.0 (14.2.1 available)
+ webdriver 3.0.3
Changed 8 dependencies!
7 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.


수정된 pubspec.yaml 파일:

# ...
dev_dependencies:
  # ... added dependencies
  flutter_test:
    sdk: flutter
  flutter_lints: ^5.0.0
  integration_test:
    sdk: flutter
# ...

 

통합 테스트 작성

통합 테스트 파일은 integration_test, flutter_test, 그리고 앱의 Dart 파일에 대한 의존성을 가진 Dart 코드 파일입니다.

1. 선호하는 IDE에서 integration_test/app_test.dart 파일을 엽니다.

2. 다음 코드를 복사하여 integration_test/app_test.dart 파일에 붙여넣습니다. 마지막 import는 counter_app의 main.dart 파일을 가리켜야 합니다. (이 예시에서는 introduction이라는 예제 앱을 가리키고 있습니다.)

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:how_to/main.dart';
import 'package:integration_test/integration_test.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('end-to-end test', () {
    testWidgets('tap on the floating action button, verify counter', (
      tester,
    ) async {
      // 앱 위젯을 로드합니다.
      await tester.pumpWidget(const MyApp());

      // 카운터가 0부터 시작하는지 확인합니다.
      expect(find.text('0'), findsOneWidget);

      // 탭할 FloatingActionButton을 찾습니다.
      final fab = find.byKey(const ValueKey('increment'));

      // FloatingActionButton을 탭하는 동작을 에뮬레이트합니다.
      await tester.tap(fab);

      // 프레임을 트리거합니다.
      await tester.pumpAndSettle();

      // 카운터가 1 증가했는지 확인합니다.
      expect(find.text('1'), findsOneWidget);
    });
  });
}

 

 

이 예제는 세 가지 단계를 거칩니다:

1. IntegrationTestWidgetsFlutterBinding을 초기화합니다. 이 싱글턴 서비스는 실제 디바이스에서 테스트를 실행할 수 있게 해줍니다.

2. WidgetTester 클래스를 사용하여 위젯과 상호작용하고 테스트합니다.

3. 중요한 시나리오를 테스트합니다.


 

통합 테스트 실행

실행 플랫폼에 따라 통합 테스트 실행 방법이 달라집니다.

  • 데스크톱 플랫폼에서 테스트하려면 명령줄 또는 CI 시스템을 사용합니다.
  • 모바일 플랫폼에서 테스트하려면 명령줄 또는 Firebase Test Lab을 사용합니다.
  • 웹 브라우저에서 테스트하려면 명령줄을 사용합니다.

 

데스크톱 플랫폼에서 테스트

macOS, Windows 또는 Linux 플랫폼에서 테스트하려면 다음 작업을 수행하세요.

1. 프로젝트 루트에서 아래 명령어를 실행합니다:

flutter test integration_test/app_test.dart

 

2. 플랫폼 선택 옵션이 표시되면 데스크톱 플랫폼을 선택합니다. 예: Windows를 선택하려면 1을 입력합니다.

 

플랫폼에 따라 아래와 같은 출력이 표시됩니다:

flutter test integration_test
Resolving dependencies... 
Downloading packages... 
  flutter_lints 3.0.2 (4.0.0 available)
> leak_tracker 10.0.4 (was 10.0.0) (10.0.5 available)
> leak_tracker_flutter_testing 3.0.3 (was 2.0.1) (3.0.5 available)
> leak_tracker_testing 3.0.1 (was 2.0.1)
  lints 3.0.0 (4.0.0 available)
  material_color_utilities 0.8.0 (0.11.1 available)
> meta 1.12.0 (was 1.11.0) (1.15.0 available)
> test_api 0.7.0 (was 0.6.1) (0.7.1 available)
> vm_service 14.2.1 (was 13.0.0) (14.2.2 available)
Changed 6 dependencies!
8 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.

Connected devices:

macOS (desktop)                 • macos                 • darwin-arm64   • macOS 14.4.1 23E224 darwin-arm64
Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin         • macOS 14.4.1 23E224 darwin-arm64
Chrome (web)                    • chrome                • web-javascript • Google Chrome 124.0.6367.208

No wireless devices were found.

[1]: macOS (macos)
[2]: Mac Designed for iPad (mac-designed-for-ipad)
[3]: Chrome (chrome)
Please choose one (or "q" to quit): 1

00:01 +0: loading /path/to/counter_app/integration_test/app_test.dart        R
00:02 +0: loading /path/to/counter_app/integration_test/app_test.dart    846ms
00:03 +0: loading /path/to/counter_app/integration_test/app_test.dart        B

Building macOS application...
✓ Built build/macos/Build/Products/Debug/counter_app.app
00:32 +1: All tests passed!

 

Android 디바이스에서 테스트

실제 Android 디바이스에서 테스트하려면 다음 작업을 수행하세요.

1. Android 디바이스를 연결합니다.

2. 프로젝트 루트에서 아래 명령어를 실행합니다:

flutter test integration_test/app_test.dart

 

출력 예시는 다음과 같습니다:

flutter test integration_test/app_test.dart
00:04 +0: loading /path/to/counter_app/integration_test/app_test.dart
00:15 +0: loading /path/to/counter_app/integration_test/app_test.dart
00:18 +0: loading /path/to/counter_app/integration_test/app_test.dart   2,387ms
Installing build/app/outputs/flutter-apk/app.apk...  612ms
00:21 +1: All tests passed!

 

3. 테스트가 끝났을 때 Counter App이 제거되었는지 확인하세요. 그렇지 않으면 이후 테스트가 실패할 수 있습니다. 필요하면 앱을 길게 눌러 컨텍스트 메뉴에서 앱 제거(Remove App) 를 선택하세요.


 

iOS 디바이스에서 테스트

실제 iOS 디바이스에서 테스트하려면 다음 작업을 수행하세요.

1. iOS 디바이스를 연결합니다.

2. 프로젝트 루트에서 아래 명령어를 실행합니다:

flutter test integration_test/app_test.dart

출력 예시는 다음과 같습니다:

flutter test integration_test/app_test.dart
00:04 +0: loading /path/to/counter_app/integration_test/app_test.dart
00:15 +0: loading /path/to/counter_app/integration_test/app_test.dart
00:18 +0: loading /path/to/counter_app/integration_test/app_test.dart   2,387ms
Xcode build done.                                           13.5s
00:21 +1: All tests passed!

 

3. 테스트가 끝난 후 앱이 제거되었는지 확인하세요. 제거되지 않았다면 이후 테스트가 실패할 수 있습니다. 필요하면 앱을 길게 눌러 앱 제거(Remove App) 를 선택하세요.

 

웹 브라우저에서 테스트하기

웹 브라우저에서 테스트하려면 다음 단계를 수행하세요.

1. 원하는 디렉터리에 ChromeDriver를 설치합니다.

npx @puppeteer/browsers install chromedriver@stable

 

설치를 간단히 하기 위해 이 명령어는 @puppeteer/browsers Node 라이브러리를 사용합니다.
2. ChromeDriver의 경로를 $PATH 환경 변수에 추가하세요.

3. ChromeDriver 설치가 성공했는지 확인하세요.

chromedriver --version
ChromeDriver 124.0.6367.60 (8771130bd84f76d855ae42fbe02752b03e352f17-refs/branch-heads/6367@{#798})

4. counter_app 프로젝트 디렉터리에서 test_driver라는 새 디렉터리를 생성합니다.

mkdir test_driver

5. 이 디렉터리에 integration_test.dart라는 새 파일을 생성합니다.

6. 다음 코드를 복사하여 integration_test.dart 파일에 붙여넣습니다.

import 'package:integration_test/integration_test_driver.dart';

Future<void> main() => integrationDriver();

7. 다음 명령으로 chromedriver를 실행합니다:

chromedriver --port=4444

8. 프로젝트 루트 디렉터리에서 다음 명령을 실행합니다:

flutter drive \
  --driver=test_driver/integration_test.dart \
  --target=integration_test/app_test.dart \
  -d chrome

 

응답은 다음과 비슷해야 합니다:

Resolving dependencies...
  leak_tracker 10.0.0 (10.0.5 available)
  leak_tracker_flutter_testing 2.0.1 (3.0.5 available)
  leak_tracker_testing 2.0.1 (3.0.1 available)
  material_color_utilities 0.8.0 (0.11.1 available)
  meta 1.11.0 (1.14.0 available)
  test_api 0.6.1 (0.7.1 available)
  vm_service 13.0.0 (14.2.1 available)
Got dependencies!
7 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.
Launching integration_test/app_test.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...             10.9s
This app is linked to the debug service: ws://127.0.0.1:51523/3lofIjIdmbs=/ws
Debug service listening on ws://127.0.0.1:51523/3lofIjIdmbs=/ws
00:00 +0: end-to-end test tap on the floating action button, verify counter
00:01 +1: (tearDownAll)
00:01 +2: All tests passed!
All tests passed.
Application finished.


이 테스트를 헤드리스 모드로 실행하려면 -d web-server 옵션을 사용하여 flutter drive를 실행하세요:

flutter drive \
  --driver=test_driver/integration_test.dart \
  --target=integration_test/app_test.dart \
  -d web-server


자세한 내용은 Running Flutter driver tests with web 위키 페이지를 참조하세요.

 

Firebase Test Lab에서 테스트하기 (Android)

Android 타겟을 테스트하기 위해 Firebase Test Lab을 사용할 수 있습니다.

 

Android 설정

README의 Android Device Testing 섹션의 지침을 따르세요.

Test Lab 프로젝트 설정

1. Firebase Console을 엽니다.

2. 필요한 경우 새 Firebase 프로젝트를 생성합니다.

3. Quality > Test Lab으로 이동합니다.

Android APK 업로드

Android APK를 업로드하려면 다음 단계를 완료하세요.

1. Gradle을 사용하여 APK를 생성합니다.

// gradlew 스크립트가 있는 Android 디렉터리로 이동
pushd android

// gradlew로 Flutter의 debug APK 빌드
// 일반적인 --release 빌드는 package:integration_test를 포함하지 않음
flutter build apk --debug

// Android 테스트 APK 빌드
./gradlew app:assembleAndroidTest

// integration test를 전달하여 debug APK 빌드
./gradlew app:assembleDebug -Ptarget=integration_test/<name>_test.dart


<name>_test.dart: 프로젝트 설정 섹션에서 생성한 파일 이름을 사용하세요.

2. 필요한 경우, 테스트에 파라미터를 Base64로 인코딩된 쉼표로 구분된 리스트로 전달할 수 있습니다:

./gradlew project:task -Pdart-defines="{base64 (key=value)}[, ...]"

 

3. 이전 디렉터리로 돌아갑니다:

popd


추가 지침은 README의 Firebase Test Lab 섹션을 참조하세요.

 

Robo 테스트 시작

Robo 테스트를 사용하여 통합 테스트를 실행하려면 다음 단계를 완료하세요.

1. Flutter 프로젝트 디렉터리의 build/app/outputs/apk/debug에 있는 debug APK를 Firebase Test Lab 웹 페이지의 Android Robo Test 대상 영역에 드래그하세요. 예:

2. "Run a test" 버튼을 클릭하세요.

3. Instrumentation test 유형을 선택합니다.

4. 앱 APK를 App APK or AAB 상자에 추가합니다:

<flutter_project_directory>/build/app/outputs/apk/debug/<file>.apk

5. 테스트 APK를 Test APK 상자에 추가합니다:

<flutter_project_directory>/build/app/outputs/apk/androidTest/debug/<file>.apk

6. 실패가 발생하면 빨간색 아이콘을 클릭하여 출력 내용을 확인하세요:

 

Firebase Test Lab에서 테스트하기 (iOS)

iOS 타겟을 테스트하기 위해 Firebase Test Lab을 사용할 수 있습니다.

iOS 설정

iOS Device Testing 지침을 따르세요.

Test Lab 프로젝트 설정

1. Firebase Console을 엽니다.

2. 필요한 경우 새 Firebase 프로젝트를 생성합니다.

3. Quality > Test Lab으로 이동합니다.

Firebase Console을 통한 Xcode 테스트 업로드

ZIP 파일을 업로드하는 방법에 대한 자세한 내용은 Firebase Test Lab iOS 지침을 참고하세요.

명령줄을 통한 Firebase Console으로의 Xcode 테스트 업로드

명령줄을 통해 ZIP 파일을 Firebase Test Lab Console로 업로드하는 방법은 iOS Device Testing 지침을 참조하세요.

반응형
댓글
공지사항