Skip to content

leancodepl/patrol

Repository files navigation

Patrol

patrol on pub.dev patrol_finders on pub.dev patrol_cli on pub.dev code style powered by

Patrol promotial graphics

Simple yet powerful Flutter-first UI testing framework overcoming limitations of flutter_test, integration_test, and flutter_driver. Created and supported by LeanCode.

Learn more about Patrol:

Patrol custom finders

Flutter's finders are powerful, but not very intuitive to use.

We took them and made something awesome.

Thanks to Patrol's custom finders, you'll take your tests from this:

testWidgets('signs up', (WidgetTester tester) async {
  await tester.pumpWidget(AwesomeApp());
  await tester.pumpAndSettle();

  await tester.enterText(
    find.byKey(Key('emailTextField')),
    'charlie@root.me',
  );
  await tester.pumpAndSettle();

  await tester.enterText(
    find.byKey(Key('nameTextField')),
    'Charlie',
  );
  await tester.pumpAndSettle();

  await tester.enterText(
    find.byKey(Key('passwordTextField')),
    'ny4ncat',
  );
  await tester.pumpAndSettle();

  await tester.tap(find.byKey(Key('termsCheckbox')));
  await tester.pumpAndSettle();

  await tester.tap(find.byKey(Key('signUpButton')));
  await tester.pumpAndSettle();

  expect(find.text('Welcome, Charlie!'), findsOneWidget);
});

to this:

patrolTest('signs up', (PatrolIntegrationTester $) async {
  await $.pumpWidgetAndSettle(AwesomeApp());

  await $(#emailTextField).enterText('charlie@root.me');
  await $(#nameTextField).enterText('Charlie');
  await $(#passwordTextField).enterText('ny4ncat');
  await $(#termsCheckbox).tap();
  await $(#signUpButton).tap();

  await $('Welcome, Charlie!').waitUntilVisible();
});

Learn more about custom finders in the docs!

Patrol's custom finders are also available standalone in the patrol_finders package.

Patrol native automation

Flutter's default integration_test package can't interact with the OS your Flutter app is running on. This makes it impossible to test many critical business features, such as:

  • granting runtime permissions
  • signing into the app which through WebView or Google Services
  • tapping on notifications
  • much more!

Patrol's native automation feature solves these problems:

void main() {
  patrolTest('showtime', (PatrolIntegrationTester $) async {
    await $.pumpWidgetAndSettle(AwesomeApp());
    // prepare network conditions
    await $.native.enableCellular();
    await $.native.disableWifi();

    // toggle system theme
    await $.native.enableDarkMode();

    // handle native location permission request dialog
    await $.native.selectFineLocation();
    await $.native.grantPermissionWhenInUse();

    // tap on the first notification
    await $.native.openNotifications();
    await $.native.tapOnNotificationByIndex(0);
  });
}

CLI

See packages/patrol_cli.

The CLI is needed to enable Patrol's native automation feature in integration tests. It also makes development of integration tests much faster thanks to Hot Restart.

To run widget tests, you can continue to use flutter test.

Package

See packages/patrol.

Patrol contracts generator

  1. (Optionally) add new request type:
class OpenAppRequest {
  late String appId;
}
  1. Add new method to NativeAutomator:
abstract class NativeAutomator<IOSServer, AndroidServer, DartClient> {
  ...
  void openApp(OpenAppRequest request);
  ...
}
  1. Run gen_from_schema script, few files will be updated

Develop patrol_cli

If you have previously activated patrol_cli run:

dart pub global deactivate patrol_cli

then

cd packages/patrol_cli
flutter pub global activate -s path .