Skip to main content
Since patrol_finders is a separate package, you can use it in your widget or golden tests without depending on the full patrol package.

Installation

1

Add the dependency

Add the patrol_finders package as a dev_dependency in your app’s pubspec.yaml:
flutter pub add patrol_finders --dev
This will add the following to your pubspec.yaml:
pubspec.yaml
dev_dependencies:
  patrol_finders: ^4.0.0
2

Import in your test files

Import patrol_finders in your test files:
test/widget_test.dart
import 'package:patrol_finders/patrol_finders.dart';
This import gives you access to the $ syntax, PatrolTester, and patrolWidgetTest().
3

Write your first test

You can now use Patrol finders in your tests!

Two Ways to Use Patrol Finders

There are two approaches to using Patrol finders in your tests: The patrolWidgetTest() function is a drop-in replacement for testWidgets() that automatically creates a PatrolTester for you:
test/patrol_widget_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol_finders/patrol_finders.dart';

void main() {
  patrolWidgetTest(
    'counter is decremented when minus button is tapped',
    (PatrolTester $) async {
      await $.pumpWidget(const MyApp());

      expect($('0'), findsOneWidget);
      expect($('-1'), findsNothing);

      await $(Icons.remove).tap();

      expect($('0'), findsNothing);
      expect($('-1'), findsOneWidget);
    },
  );
}
By convention, we name the PatrolTester parameter $ to keep test code concise and readable.

Option 2: Manual PatrolTester Creation

If you need more control, you can manually create a PatrolTester inside a regular testWidgets() call:
test/widget_test_with_patrol_finders.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol_finders/patrol_finders.dart';

void main() {
  testWidgets(
    'counter is decremented when minus button is tapped',
    (WidgetTester tester) async {
      PatrolTester $ = PatrolTester(
        tester: tester,
        config: PatrolTesterConfig(),
      );
      
      await $.pumpWidget(const MyApp());

      expect($('0'), findsOneWidget);
      expect($('-1'), findsNothing);

      await $(Icons.remove).tap();

      expect($('0'), findsNothing);
      expect($('-1'), findsOneWidget);
    },
  );
}

Configuration

You can customize Patrol’s behavior using PatrolTesterConfig:
patrolWidgetTest(
  'logs in successfully',
  config: PatrolTesterConfig(
    // How long to wait for widgets to become visible
    visibleTimeout: Duration(seconds: 20),
    
    // How long to wait for widgets to exist
    existsTimeout: Duration(seconds: 10),
    
    // Timeout for pumpAndSettle operations
    settleTimeout: Duration(seconds: 10),
    
    // Default settle policy for actions
    settlePolicy: SettlePolicy.trySettle,
    
    // Duration for drag gestures during scrolling
    dragDuration: Duration(milliseconds: 100),
    
    // Timeout for settling between scroll gestures
    settleBetweenScrollsTimeout: Duration(seconds: 5),
    
    // Enable logging (useful for debugging)
    printLogs: true,
  ),
  ($) async {
    // Your test code
  },
);
patrolWidgetTest(
  'waits for slow loading widget',
  config: PatrolTesterConfig(
    visibleTimeout: Duration(seconds: 30),
  ),
  ($) async {
    await $.pumpWidget(const MyApp());
    await $('Loaded content').waitUntilVisible();
  },
);

Running Your Tests

Run your tests using the standard Flutter test command:
flutter test
Or run a specific test file:
flutter test test/widget_test.dart

Next Steps

Learn Basic Usage

Discover how to find widgets, make assertions, and perform actions

Explore Advanced Features

Master complex scenarios and advanced techniques

Build docs developers (and LLMs) love