Widget testing helps you check if parts of your app look and work correctly. It finds problems early so your app is better.
Widget testing in Flutter
Introduction
Syntax
Flutter
testWidgets('description', (WidgetTester tester) async { await tester.pumpWidget(MyWidget()); expect(find.text('Hello'), findsOneWidget); await tester.tap(find.byType(ElevatedButton)); await tester.pump(); expect(find.text('Clicked'), findsOneWidget); });
testWidgets is the main function to write widget tests.
WidgetTester helps you build and interact with widgets in tests.
Examples
Flutter
testWidgets('finds a Text widget', (tester) async { await tester.pumpWidget(Text('Hi')); expect(find.text('Hi'), findsOneWidget); });
Flutter
testWidgets('tap button changes text', (tester) async { await tester.pumpWidget(MyButtonWidget()); expect(find.text('Press me'), findsOneWidget); await tester.tap(find.byType(ElevatedButton)); await tester.pump(); expect(find.text('Pressed'), findsOneWidget); });
Sample App
This test builds a button widget that changes its text when tapped. It first checks the initial text, taps the button, then checks the updated text.
Flutter
import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; class MyButtonWidget extends StatefulWidget { @override State<MyButtonWidget> createState() => _MyButtonWidgetState(); } class _MyButtonWidgetState extends State<MyButtonWidget> { String buttonText = 'Press me'; void _changeText() { setState(() { buttonText = 'Pressed'; }); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: ElevatedButton( onPressed: _changeText, child: Text(buttonText), ), ), ), ); } } void main() { testWidgets('Button text changes when tapped', (WidgetTester tester) async { await tester.pumpWidget(MyButtonWidget()); expect(find.text('Press me'), findsOneWidget); await tester.tap(find.byType(ElevatedButton)); await tester.pump(); expect(find.text('Pressed'), findsOneWidget); }); }
Important Notes
Use pumpWidget to build your widget inside the test environment.
Use find to locate widgets by text, type, or key.
Call pump() after interactions to update the UI.
Summary
Widget testing checks if UI parts look and behave as expected.
Use testWidgets with WidgetTester to write tests.
Interact with widgets and verify changes using find and expect.
Practice
1. What is the main purpose of
testWidgets in Flutter widget testing?easy
Solution
Step 1: Understand
testWidgetsroletestWidgetsis designed to test widgets individually, focusing on UI and interaction.Step 2: Differentiate from other test types
Integration tests cover multiple screens, deployment is unrelated, and unit tests target logic, not UI.Final Answer:
To build and test a widget's UI and behavior in isolation -> Option AQuick Check:
Widget testing = isolated UI test [OK]
Hint: Remember: testWidgets tests one widget at a time [OK]
Common Mistakes:
- Confusing widget tests with integration tests
- Thinking testWidgets deploys the app
- Mixing unit tests with widget tests
2. Which of the following is the correct way to pump a widget inside a
testWidgets function?easy
Solution
Step 1: Recall the async nature of pumpWidget
pumpWidgetis asynchronous and requiresawaitto complete building the widget.Step 2: Identify correct method name and usage
OnlypumpWidgetis valid;runWidgetandbuildWidgetdo not exist.Final Answer:
await tester.pumpWidget(MyWidget()); -> Option BQuick Check:
Use await with pumpWidget [OK]
Hint: Always await pumpWidget to build widgets in tests [OK]
Common Mistakes:
- Forgetting to use await with pumpWidget
- Using non-existent methods like runWidget
- Calling pumpWidget without await
3. Given this test code snippet, what will the test find?
testWidgets('Finds a Text widget', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(
body: Text('Hello Flutter'),
),
));
final textFinder = find.text('Hello Flutter');
expect(textFinder, findsOneWidget);
});medium
Solution
Step 1: Analyze the widget tree built
The code builds a MaterialApp with a Scaffold containing a Text widget with 'Hello Flutter'.Step 2: Check the finder and expectation
The finder looks for text 'Hello Flutter' which exists exactly once, so expect findsOneWidget will pass.Final Answer:
The test will pass because the Text widget with 'Hello Flutter' exists -> Option DQuick Check:
Text widget found = test passes [OK]
Hint: Check widget tree and finder text carefully [OK]
Common Mistakes:
- Assuming test fails without MaterialApp (it is provided)
- Misreading the text string in finder
- Expecting multiple widgets but only one exists
4. Identify the error in this widget test code:
testWidgets('Tap button increments counter', (WidgetTester tester) async {
await tester.pumpWidget(MyCounterWidget());
await tester.tap(find.byType(ElevatedButton));
expect(find.text('1'), findsOneWidget);
});medium
Solution
Step 1: Check test flow after tap
After tapping, the UI needs to update, sotester.pump()ortester.pumpAndSettle()must be awaited.Step 2: Identify missing pump after tap
The code missesawait tester.pump()after tap, so the UI does not update before the expect check.Final Answer:
Missing await after tap before expect -> Option AQuick Check:
Always pump after tap to update UI [OK]
Hint: Pump UI after tap before checking results [OK]
Common Mistakes:
- Forgetting to pump after user interaction
- Using incorrect finder types
- Not awaiting async calls
5. You want to test a widget that shows a loading spinner while fetching data, then displays the data text. Which sequence correctly tests this behavior?
hard
Solution
Step 1: Understand loading and data display sequence
The widget first shows a spinner while loading, then after data loads, shows the data text.Step 2: Test sequence to verify UI changes
First pump the widget and check spinner is visible. Then callpumpAndSettleto wait for animations and updates, then verify data text is visible.Final Answer:
Pump widget, verify spinner visible, pumpAndSettle, verify data text visible -> Option CQuick Check:
Spinner first, then data after settle [OK]
Hint: Check loading UI before and after pumpAndSettle [OK]
Common Mistakes:
- Checking data text before loading finishes
- Not using pumpAndSettle to wait for UI updates
- Assuming spinner hides without pumping
Recommended
Ready to prove it?
Pass the test and this pattern moves unknown
10 questions ~5 mineasy hard
