Flutter Widget Test: solved UI testing exercise

  2 minutes

If you are looking for Flutter widget test, this solved exercise gives you a practical implementation pattern you can reuse in real projects.

Build a screen with:

  • render a counter widget
  • tap button in test
  • assert updated UI state
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class CounterWidget extends StatefulWidget {
  const CounterWidget({super.key});

  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: [
            Text('$count'),
            ElevatedButton(onPressed: () => setState(() => count += 1), child: const Text('Add')),
          ],
        ),
      ),
    );
  }
}

void main() {
  testWidgets('increments counter when tapped', (tester) async {
    await tester.pumpWidget(const CounterWidget());

    expect(find.text('0'), findsOneWidget);
    await tester.tap(find.text('Add'));
    await tester.pump();
    expect(find.text('1'), findsOneWidget);
  });
}

The test verifies interaction behavior and protects against future regressions.

  • Forgetting pump after interactions.
  • Overfitting tests to fragile layout details.
  • Skipping critical user paths.

Widget tests reduce UI regressions and speed up confident refactors.

Unit tests validate isolated logic, widget tests validate rendered UI behavior.

Not always. Add integration tests for full multi-screen flows.

As early as possible, especially for critical interactions.