はじめに
FlutterのFinderやWidgetTesterではネイティブビュー(OSの権限許可ダイアログ等)を見つけたり操作することができません。
そこで、patrolを使用して操作できるようにしたいと思います。
続き -> 【Flutter】Patrolでテストを書く(テスト編)
本記事ではpatrolを導入し、iOSとAndroidのセットアップまで進めます。
環境
・flutter: 3.19.6
・dart: 3.3.4
・patrol: 3.6.1
・patrol_cli: 2.7.0
patrol、patrol_cliのインストール
patrolを追加
flutter pub add patrol --dev
※Android SDK versionは21以上
android {
// ----- 省略 ----- //
defaultConfig {
minSdkVersion 21
// ----- 省略 ----- //
}
pubspec.yamlにpatrolセクションを追加
・app_name、package_name、bundle_idはそれぞれ自身のアプリの値に置き換える
dependencies:
# ...
dev_dependencies:
# ...
patrol:
app_name: My App
android:
package_name: com.example.myapp
ios:
bundle_id: com.example.MyApp
app_name等の確認方法
・app_name
<application
android:label="アプリ名"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<key>CFBundleName</key>
<string>アプリ名</string>
・package_name
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
android {
// ----- 省略 ----- //
defaultConfig {
applicationId "com.example.myapp"
// ----- 省略 ----- //
}
}
・bundle_idはInfo.plistで直接見ることができないので、ios/Runner.xcworkspaceをXcodeで開いて確認
patrol_cliを追加
dart pub global activate patrol_cli
patrolのPATHを通す(patrol_cliのREADMEを参照)
・Dartバージョンを確認(記事作成時点では2.18以上が必要とあるが、patrol_cliのバージョンによって変わりそう?バージョンが足りなければ後続のコマンドでエラーになって分かるので、そこで再度確認するでもいいと思います)
dart --version
・patrolをcloneする
・cloneする場所はアプリ内である必要はないのでどこでもいい
git clone git@github.com:leancodepl/patrol.git
・packages/patrol_cliに移動
cd patrol/packages/patrol_cli
・以下を実行
dart pub global activate --source path .
・patrol doctorを実行して出力が全てグリーンになればOK
$ patrol doctor
Patrol doctor:
Patrol CLI version: 2.7.0
Flutter command: flutter
Flutter 3.19.5 • channel stable
Android:
• Program adb found in /Users/username/Library/Android/sdk/platform-tools/adb
• Env var $ANDROID_HOME set to /Users/username/Library/Android/sdk
iOS / macOS:
• Program xcodebuild found in /usr/bin/xcodebuild
• Program ideviceinstaller found in /usr/local/bin/ideviceinstaller
Androidセットアップ
①android/app/src/androidTest/java/com/example/myapp/に移動。フォルダがなければ作成する。com/example/myapp/の部分はpubspec.yamlに記述したpackage_nameに置き換える
②MainActivityTest.javaという名前のファイルを作成し、以下のコードをコピペする
※package com.example.myapp;の部分は自身のpackage_nameに書き換える
MainActivityTest.java
package com.example.myapp; // replace "com.example.myapp" with your app's package
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import pl.leancode.patrol.PatrolJUnitRunner;
@RunWith(Parameterized.class)
public class MainActivityTest {
@Parameters(name = "{0}")
public static Object[] testCases() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
// replace "MainActivity.class" with "io.flutter.embedding.android.FlutterActivity.class"
// if your AndroidManifest is using: android:name="io.flutter.embedding.android.FlutterActivity"
instrumentation.setUp(MainActivity.class);
instrumentation.waitForPatrolAppService();
return instrumentation.listDartTests();
}
public MainActivityTest(String dartTestName) {
this.dartTestName = dartTestName;
}
private final String dartTestName;
@Test
public void runDartTest() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
instrumentation.runDartTest(dartTestName);
}
}
③build.gradleのdefaultConfigに以下の2行を追加
android {
// ----- 省略 ----- //
defaultConfig {
// ----- 省略 ----- //
testInstrumentationRunner "pl.leancode.patrol.PatrolJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: "true"
}
④build.gradleのandroidに以下を追加
android {
// ----- 省略 ----- //
testOptions {
execution "ANDROIDX_TEST_ORCHESTRATOR"
}
⑤build.gradleのdependenciesに以下を追加
dependencies {
androidTestUtil "androidx.test:orchestrator:1.4.2"
}
iOSセットアップ
①ios/Runner.xcworkspaceをXcodeで開く
②テストTARGETSがなければ作成する。注意点として言語はSwiftではなくObjective-Cである必要がある
-
File > New > Target...でUI Testing Bundleを選択 -
Product NameをRunnerUITestsにする -
Organization Identifierをpubspec.yamlに記述したbundle_idと同じにする -
LanguageをObjective-Cに設定 -
Target to be TestedにRunnerが設定されていること確認 -
Finishを選択
③RunnerUITests.mとRunnerUITestsLaunchTests.mが作成されるので、RunnerUITestsLaunchTests.mを選択してdelete > Move to Trashで削除
④RunnerとRunnerUITestsのBuild Settings > iOS Deployment Targetを同じにする
⑤RunnerUITests.mを以下に置き換える
@import XCTest;
@import patrol;
@import ObjectiveC.runtime;
PATROL_INTEGRATION_TEST_IOS_RUNNER(RunnerUITests)
⑥PodfileにRunnerUITestsのtargetを追加
target 'Runner' do
# Do not change existing lines.
target 'RunnerUITests' do
inherit! :complete
end
end
⑦アプリのルートにintegration_test/example_test.dartを作成し、以下のコマンドを実行する。(example_test.dartは空のファイル)
flutter build ios --config-only integration_test/example_test.dart
⑧iosディレクトリに移動し、以下のコマンドを実行
pod install --repo-update
⑨Runnerのinfoを確認し、RunnerUITestsの構成をRunnerと同じにする

⑩RunnerUITests > Build Phasesに移動し、左上の+アイコンからNew Run Script Phaseを選択。xcode_backend buildとxcode_backend embed_and_thinという名前の2つの新しいRun Script Phaseを追加する
⑪新しく作成したRun Script Phaseを以下の通りに並べ替える

⑫xcode_backend buildに以下を追加
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
⑬xcode_backend embed_and_thinに以下を追加
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed_and_thin
⑭全てのschemeのparallel executionの設定を無効にする。設定の場所はこちらの動画を確認
⑮RunnerUITests > Build Settingsに移動し、User Script Sandboxingを検索してNoに設定する
おわりに
長かったですが、以上でセットアップ完了です。エラーが発生した場合はFAQも参考になるかもしれません。
次回はテストを書いていこうと思います。


