← Flutter / Dart

Flutter / Dart · 15 / 18

Unit and widget tests with meaningful expectations

Verify domain rules and visible behaviour rather than only code existence.

  • Medium
  • Intermediate
  • 45 min

Prerequisites: Coordinate photos, files and PDF output

A unit test checks a small rule without an interface. A widget test builds an interface and triggers user actions. Both should express a meaningful expectation. A test merely retelling the implementation can repeat the same mistake. We check the counter from tutorial 09, then examine Vehicle File’s real service and PDF tests.

Example files

01Restore the starting screen

Use main.dart from tutorial 09 in the learning project. Create test/counter_test.dart. The ../lib/main.dart import refers to that screen. flutter_test is available as a development dependency in the Flutter project.

counter_test.dart · dartOpen file
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import '../lib/main.dart';

void main() {
  testWidgets('adding an entry changes the displayed count', (tester) async {
    await tester.pumpWidget(const MaterialApp(home: CounterScreen()));
    expect(find.text('Entries: 0'), findsOneWidget);
    await tester.tap(find.text('Add entry'));
    await tester.pump();
    expect(find.text('Entries: 1'), findsOneWidget);
    expect(find.text('Entries: 0'), findsNothing);
  });
}

Run / check

flutter test test/counter_test.dart

02Check before and after

pumpWidget builds the interface. find.text finds visible text. tap triggers a click. pump processes the next frame. We expect 0 before the action and 1 afterwards. Without the second check, an inactive button could go unnoticed.

03Derive failure cases from domain rules

For services, test empty names, invalid readings and failing storage. The real suite also checks backup passwords, PDF attachments and transaction boundaries. Mocks help control failures. Real database tests additionally verify adapter behaviour.

04Deliberately make the test fail

Change count++ in the screen to count += 2. The test must fail. Then restore the change. A test is useful evidence only if it detects a specific incorrect change.

Expected result

flutter test test/counter_test.dart passes. Incrementing by 2 fails the Entries: 1 expectation.

Your exercise

Add a second click and check the Entries: 2 display.

Show the solution and explanation

Run tap and pump again and expect findsOneWidget for Entries: 2. Also verify Entries: 1 no longer exists. This confirms visible behaviour across several actions.

Project context and sources

The example is simplified for learning. The linked source version shows its use in the project and the checks applied there.