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.
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.
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.dart02Check 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.
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.