Advanced

Patrol section in pubspec.yaml

If your app has different name on iOS and Android, you can specify app_name twice – one in android block, and one in ios block.

Though the whole Patrol section in pubspec.yaml is optional, we highly recommend adding this section, because it enables the following features:

  • Patrol will automatically uninstall your app after every test (using package_name and bundle_id). This will make the environment which your tests run in more stable and predictable.
  • Patrol will be able to tap on your app's notifications (using app_name)

Specific version of patrol_cli

You can install a specific version of Patrol CLI. For example:

dart pub global activate patrol_cli ^1.0.0

will install the latest v1 version. We recommend to install a specific version on CI systems to avoid unexpected breakages.

Isolation of test runs

To achieve full isolation between test runs, enable the clearPackageOption:

android/app/build.gradle
defaultConfig {
    //...
    testInstrumentationRunner "pl.leancode.patrol.PatrolJUnitRunner"
    testInstrumentationRunnerArguments clearPackageData: "true"
}

This will clear the app's data and permissions before each test run. Unfortunately, no equivalent feature is available on iOS.

Embrace the native tests

If you've diligently followed the steps in native automation setup and patrol test prints a TEST PASSED message, you might be now thinking: what did I just do?

The answer is: You've just integrated Flutter testing with native Android/iOS testing frameworks. This means that your Flutter integration tests can now be run as native tests.

What are native tests good for, anyway?

iOS and Android have existed for more than 15 years, and during that time many of awesome testing-related things were built around them – open-source test runners, device farms, HTML report generators. Developers who create native mobile apps can easily reap benefits from this huge, mature ecosystem.

Meanwhile we, Flutter developers, don't have as much at our disposal. Our framework is much younger and less mature.

What if we could masquerade our Flutter tests so that from the outside they would be truly native? This way we leverage many existing tools while maintaining the convenience of writing the tests in pure Dart.

For example, you can run your Patrol tests directly from Xcode. Xcode knows nothing about Flutter, Dart and Patrol – it only launches your test app. Flutter tests are then run inside the test app and the results are reported back to Xcode. This way you get the best of both worlds – the maturity of native iOS development and the productivity of Flutter and Dart.

That's exactly what Patrol does (and what the default integration_test package does at well, but at a bit smaller scale).

Take a look at this simple Flutter integration tests using Patrol:

integration_test/example_test.dart
void main() {
  patrolTest(
    'counter state is the same after going to Home and switching apps',
    nativeAutomatorConfig: NativeAutomatorConfig(
      packageName: 'pl.leancode.patrol.example',
      bundleId: 'pl.leancode.patrol.Example',
    ),
    ($) async {
      await $.pumpWidget(ExampleApp());

      await $(FloatingActionButton).tap();
      expect($(#counterText).text, '1');

      await $.native.pressHome();
      await $.native.openApp();

      expect($(#counterText).text, '1');

      await $(FloatingActionButton).tap();
      expect($(#counterText).text, '2');
    },
  );
}

You can run this test and view its results in many ways, using all sorts of different tools, platforms, and IDEs:

When Android test finishes, its test results are automatically generated in build/app/outputs/androidTest-results/connected/test-result.pb. To view them in Android Studio, use the Run > Import tests from file option.

Test results in Android Studio

This is so awesome!