"소용없어요! Flutter의 통합 테스트로는 엔드투엔드 테스트를 실행할 수 없습니다."라고 약 9개월 전 고객 중 한 명이 말했습니다. 문제가 무엇인지 물었고 그들은 로그인에 Google 인증을 사용하고 있으며 google_sign_in 패키지를 사용했지만 Flutter의 통합 테스트를 사용하여 로그인 화면과 상호 작용하는 것이 불가능하다고 설명했습니다. 나는 여전히 문제가 무엇인지 잘 이해하지 못했고 클릭했습니다. 이 플러그인은 통합 테스트가 작동하지 않는 기본 UI 구성 요소를 사용합니다.
당시에는 해결책을 제시할 수 없었고 그대로 두어야 한다는 사실에 상당히 실망했습니다. 그러나 오늘날로 빠르게 나아가서 "Patrol" 이라는 놀라운 새 솔루션이 제시되었습니다.
개발팀이 다음과 같은 CI( 지속적 통합 ) 서비스를 사용하는 주요 이유 중 하나입니다.
CI 워크플로의 일부로 자동화할 수 있는 네 가지 주요 테스트 방법이 있습니다. 테스트는 그 자체로 중요한 주제이므로 간단히 설명하겠습니다. 그러나 이러한 테스트 방법을 조합하여 사용하면 앱 품질을 향상하고 문제를 더 빨리 발견하는 데 도움이 됩니다.
첫째, 함수와 메서드를 별도로 테스트하여 예상대로 작동하는지 확인하는 데 일반적으로 사용되는 "단위 테스트" 가 있습니다. 예상치 못한 결과 없이 비즈니스 논리가 다양한 시나리오에서 작동하는지 확인하기 위해 단위 테스트를 작성할 수도 있습니다.
다음으로, UI 구성 요소를 테스트하고 올바르게 렌더링되고 예상대로 작동하는지 확인할 수 있는 Flutter "위젯 테스트"가 있습니다.
그런 다음 애플리케이션의 단위와 구성 요소가 예상대로 함께 작동하는지 테스트하는 "통합 테스트"가 있습니다.
마지막으로 실제 사용자가 사용하는 것처럼 애플리케이션을 테스트하는 "End-to-End UI 테스트"가 있습니다. CI 워크플로에서는 일반적으로 시뮬레이터나 에뮬레이터를 사용하여 자동화되어 앱을 통해 다양한 경로를 테스트하여 코드를 변경한 후 문제가 없는지 확인합니다.
처음에 제가 얘기했던 고객이 앱에 로그인할 수 없어 엔드투엔드 UI 테스트를 실행할 수 없어서 멈춘 곳입니다. 당시 그들은 로그인 부분을 우회하는 '개발자' 버전을 테스트했습니다.
그러나 이제 "순찰"을 사용할 수 있으므로 더 이상 필요하지 않습니다!
그럼 먼저 패트롤(Patrol)이란 무엇일까요? 글쎄, 내 생각에는 문서가 가장 잘 말한 것 같습니다.
Patrol은 LeanCode에서 개발한 Flutter용 새로운 오픈 소스 UI 테스트 프레임워크입니다. Flutter의 기존 테스트 도구를 기반으로 구축되어 이전에는 불가능했던 작업을 수행할 수 있습니다. Patrol을 사용하면 Flutter 앱이 실행되는 플랫폼의 기본 기능에 액세스할 수 있습니다.
여기서 가장 중요한 부분은 Flutter 앱이 실행되는 플랫폼의 기본 기능 에 액세스할 수 있다는 것입니다.
이는 이제 다음과 같은 작업을 수행할 수 있음을 의미합니다.
좋아, 듣기에는 좋은데 문제가 뭐야?
글쎄, 하나도 없어! 게다가 무료 일 뿐만 아니라
또한 Patrol은 테스트 작성을 위한 보다 간결한 구문을 제공하는 '사용자 정의 파인더' 도 도입합니다. 당신은 그들에 대해 더 많은 것을 읽을 수 있습니다
Patrol을 시작하려면 CLI를 설치하고, pubspec.yaml 에 Patrol 종속성을 추가하고, iOS 및 Android 프로젝트에서 일부 구성을 설정해야 합니다.
LeanCode는 훌륭한 문서를 만들었습니다.
문제가 발생하면 도움을 받을 수 있는 가장 좋은 곳은 Patrol Community Discord 서버에 참여하는 것입니다.
버그를 발견하면 문제를 제기할 수 있습니다.
Patrol을 시작하려면 CLI를 설치하고, pubspec.yaml 에 Patrol 종속성을 추가하고, iOS 및 Android 프로젝트에서 일부 구성을 설정해야 합니다.
LeanCode는 훌륭한 문서를 만들었습니다.
문제가 발생하면 도움을 받을 수 있는 가장 좋은 곳은 Patrol Community Discord 서버에 참여하는 것입니다.
버그를 발견하면 문제를 제기할 수 있습니다.
이제 모든 설정이 완료되었습니다. 몇 가지 기본 기능을 테스트해 보겠습니다. 직접 사용해 보기 위해 클릭하면 기본 경고 대화 상자가 열리는 상승된 버튼이 있는 간단한 Flutter 앱을 설정했습니다.
"확인" 또는 "취소"를 클릭하면 대화상자가 닫힙니다.
다시 한 번 말씀드리지만, 찾을 수 있는 Patrol의 자체 문서를 사용하는 것이 좋습니다.
그래서 테스트를 위해 "Click me!"라는 텍스트가 있는 높은 버튼을 클릭하고 싶었습니다. 이는 표준 Flutter 위젯이므로 다음 Patrol Finder를 사용하여 탭할 수 있습니다.
await $('Click me!').tap();
그러면 기본 대화 상자가 표시되므로 이제 기본 UI 구성 요소와 상호 작용을 시작할 수 있습니다. 이제 "확인" 버튼을 탭할 수 있는 기본 파인더를 추가해 보겠습니다.
await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK'));
그것은 쉽다! "취소" 버튼도 테스트하고 싶으므로 "클릭하세요!"를 탭해 보겠습니다. 버튼을 다시 누른 다음 다음과 같이 몇 줄을 더 추가하여 기본 대화 상자의 "취소" 버튼을 탭합니다.
await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'Cancel'));
완성된 테스트 파일은 다음과 같습니다.
import 'package:cmpatrol/main.dart'; import 'package:patrol/patrol.dart'; void main() { patrolTest( 'Native tests', nativeAutomation: true, ($) async { await $.pumpWidgetAndSettle(const MyApp()); await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'Cancel')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'NO')); }, ); }
이제 테스트를 시작하는 명령을 사용하여 에뮬레이터나 실제 장치에서 해당 테스트를 실행할 수 있습니다. 내 통합 테스트 파일은 "button_test" 이므로 다음과 같이 터미널에서 테스트를 시작했습니다.
patrol test -t integration_test/button_test.dart
테스트의 통과 여부를 터미널에서 직접 확인할 수 있습니다. 테스트가 실패하면 전체 테스트 보고서에 대한 링크가 제공됩니다. 또는 제가 했던 것처럼 Android에서 테스트를 실행하는 경우 다음 디렉터리에 있는 index.html 을 클릭하여 보고서에 액세스할 수 있습니다.
./build/app/reports/androidTest/connected
알림 트레이 열기, Wi-Fi 비활성화, 다크 모드 활성화, 앱 최소화 및 최대화와 같은 기타 기본 기능을 추가로 실험해 볼 수 있습니다.
// minimize app await $.native.pressHome(); await $.native.openNotifications(); await $.native.disableWifi(); await $.native.enableDarkMode(); // maximize app await $.native.openApp();
⚠️ 앱을 완전히 닫았다가 다시 여는 것은 불가능합니다. 그렇게 하면 전체 테스트가 종료되어 실패하게 되기 때문입니다.
순찰대에 문의하세요
Patrol을 워크플로에 통합하려면 먼저 빌드 시스템에 Patrol CLI를 설치해야 합니다. 이 작업은 몇 초 밖에 걸리지 않으며 완료되면 테스트 스크립트를 실행할 수 있습니다. 다음은 codemagic.yaml 구성 파일의 "스크립트" 섹션에 이러한 단계를 추가하는 방법의 예입니다. 첫 번째 스크립트 단계 중 하나로 Patrol CLI를 설치하는 스크립트를 실행한 다음 그 직후 또는 미리 실행하고 싶은 다른 테스트 후에 Patrol 테스트를 실행할 수 있습니다.
순찰 테스트를 실행하기 전에 에뮬레이터를 시작해야 합니다. 그러면 에뮬레이터를 시작하고 완전히 부팅될 때까지 기다리는 스크립트를 추가하겠습니다. Apple Virtualization Framework가 중첩된 가상화를 지원하지 않기 때문에 Apple Silicon M1 또는 M2 시스템을 사용하는 시스템에서는 Android 에뮬레이터를 사용할 수 없습니다. 따라서 Android 앱을 테스트할 때는 Linux 인스턴스를 사용하는 것이 좋습니다.
codemagic.yaml 의 스크립트 섹션은 다음과 같아야 합니다.
scripts: ... - name: Install Patrol CLI script: dart pub global activate patrol_cli - name: Launch Android emulator script: | cd $ANDROID_HOME/tools emulator -avd emulator & adb wait-for-device - name: Run tests with Patrol script: patrol test -t integration_test/your_test.dart ignore_failure: true ...
순찰 테스트 결과는 JUnit XML 형식으로도 제공됩니다. 즉, Codemagic 빌드 개요 화면의 빌드 로그에 표시될 수 있습니다. 생성된 JUnit XML 파일의 경로에 test_report 속성 전달을 추가하기만 하면 됩니다. 부울과 함께 ignore_failure 속성을 사용하여 워크플로의 나머지 부분을 계속 실행할지 여부를 제어할 수 있습니다. 다음 섹션에 설명된 대로 결과를 테스트 관리 시스템에 업로드하려면 이를 true 로 설정해야 합니다.
다음은 스크립트의 모양에 대한 예입니다.
scripts: ... - name: Run tests with Patrol script: | patrol test -t integration_test/your_test.dart test_report: build/app/outputs/androidTest-results/connected/*.xml ignore_failure: true ...
실패한 테스트는 다음과 같을 수 있습니다.
추가로 수행할 수 있는 작업 중 하나는 테스트 보고서 출력을 빌드 아티팩트로 수집하여 오류가 발생할 경우 전체 보고서를 볼 수 있도록 하는 것입니다. 이렇게 하면 왼쪽의 "아티팩트" 섹션에 있는 빌드 개요 화면에서 보고서를 zip 파일로 다운로드할 수 있습니다. 이를 수행하는 가장 쉬운 방법은 보고서 파일이 있는 디렉터리를 Codemagic이 아티팩트를 내보내는 데 사용하는 디렉터리로 복사하는 것입니다. 스크립트에서 사용할 수 있는 이 디렉터리를 참조하는 $CM_EXPORT_DIR 이라는 내장 환경 변수가 있습니다.
이를 수행하는 스크립트는 다음과 같아야 합니다.
scripts: ... - name: Export Patrol test report script: | cp -r build/app/reports/androidTests/connected $CM_EXPORT_DIR/report ...
Patrol은 마침내 기본 기능과 관련된 UI 및 통합 테스트 실행 문제를 극복했습니다. 이제 기본 기능을 테스트하고 인증 흐름, 기본 대화 상자와 상호 작용할 수 있으며 Wi-Fi, 셀룰러, 다크 모드와 같은 기본 기능을 전환하고 앱을 최소화하고 최대화할 수도 있습니다. 또한 이는 무료 이자 오픈 소스 이며 Flutter가 출시된 이후 계속 있었던 실제 문제에 대한 솔루션을 제공합니다. 게다가 Codemagic 워크플로에 추가하고 사용하는 것도 간단합니다. LeanCode가 하고 있는 훌륭한 작업을 지원하고 싶다면 Patrol에게 pub.dev에 좋아요를 눌러주세요.
이 기사는 솔루션 엔지니어링 책임자인 Kevin Suhajda가 작성했습니다.
여기에도 게시되었습니다.