How do you write a basic widget test in Flutter?
// short answer
Use testWidgets() with a WidgetTester, pump your widget with tester.pumpWidget(), then use finders (like find.text or find.byType) combined with matchers (like findsOneWidget) to assert on what's rendered.
Widget tests run in a simulated environment (no real device needed) and are faster than full integration tests while still testing actual widget rendering and interaction, unlike pure unit tests. tester.pumpWidget(widget) builds the widget tree; tester.pump() advances a single frame (needed after state changes); tester.pumpAndSettle() repeatedly pumps until no more frames are scheduled, useful for animations to finish.
find.text('Login'), find.byType(ElevatedButton), and find.byKey(someKey) locate widgets, and expect(finder, findsOneWidget) (or findsNothing, findsNWidgets(n)) asserts on what's present.
// code example
testWidgets('shows error on empty submit', (tester) async {
await tester.pumpWidget(const MaterialApp(home: LoginScreen()));
await tester.tap(find.text('Submit'));
await tester.pump();
expect(find.text('Email is required'), findsOneWidget);
});// common mistakes
- ×Forgetting to wrap the widget under test in a MaterialApp, causing errors about missing Directionality/Theme ancestors.
- ×Using tester.pump() when tester.pumpAndSettle() is needed (e.g. after a navigation transition or animation), leading to flaky assertions.