WidgetTester: Programmatically Drive Your Flutter UI
WidgetTester is a robot user for your app, programmatically tapping, dragging, and entering text. Use it in `testWidgets` to simulate user flows and verify UI state. The footgun is forgetting `tester.pump()` after an action; you'll assert against a stale UI.
WHY IT EXISTS: To test a widget's behavior, you need to simulate how a user interacts with it and how it responds over time. Manually testing every tap and scroll is slow and error-prone. WidgetTester provides a programmatic way to automate these interactions in a controlled, repeatable test environment.
THE MENTAL MODEL: WidgetTester is a robot user for your app that also controls time. It can find a widget on the screen (like a button with the text 'Save'), perform an action on it (like a tap), and then fast-forward time to see the result (like a 'Success' message appearing). It replaces a human finger with code.
HOW IT WORKS: A test starts by loading your widget tree using tester.pumpWidget(). You then use Finders (e.g., find.text('Submit')) to locate specific widgets. Once found, you can call action methods like tester.tap(), tester.drag(), or tester.enterText(). The key is the tester.pump() method. Every time you call it, you tell Flutter to advance a single frame, rebuilding widgets and processing animations. Calling pump(Duration(seconds: 1)) fast-forwards time, completing any timers or animations within that duration instantly. Finally, you use expect() with matchers like findsOneWidget to verify the UI is in the expected state.
WHEN TO USE IT: Use WidgetTester inside testWidgets blocks for almost all your UI testing needs. It's ideal for verifying that: first, user input triggers the correct state changes; second, widgets render correctly based on their state; and third, complex user flows involving multiple steps work as intended.
WHEN NOT TO USE IT: WidgetTester is not for pure business logic that has no UI component; use a standard test() for that. It also doesn't run on a real device, so it can't test platform-specific integrations like camera access or push notifications. For that, you would need a full integration test using a tool like patrol.
ONE CANONICAL EXAMPLE: A common test is verifying a form submission. First, you'd use tester.pumpWidget() to load the form. Then, tester.enterText(find.byType(TextField), 'user input') to fill a field. Next, tester.tap(find.text('Save')). Crucially, you must then call await tester.pump() to let the UI react to the tap, perhaps showing a loading indicator. After the work is done (simulated with another pump), you would expect(find.text('Success'), findsOneWidget) to confirm the flow completed.
Read the original → api.flutter.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.