Veröffentlicht · wird verbessert
Flutter-Anleitung · 5/6
Dieses Kapitel ist vorerst nur auf Englisch verfügbar.
Flutter ships its testing tools with the SDK. Tests fall into three groups by scope: unit tests check a single function or class, widget tests check a widget or a small part of a screen, and integration tests run the whole app on a real device or emulator. The broader the test, the more realistic and the slower it is, so write many unit and widget tests and keep integration tests for critical flows.
| Kind | Scope | Runs on | Speed |
|---|---|---|---|
| Unit test | Functions, classes, state logic | Dart VM | Very fast |
| Widget test | Widgets, parts of screens | Simulated test environment | Fast |
| Integration test | Full app flows | Device, emulator or desktop | Slow |
Put test files in the test folder and end their names with _test.dart. In Flutter projects, the flutter_test package also provides test, group and expect.
// lib/cart.dart
class Cart {
final Map<String, int> _prices = {};
void add(String name, int price) => _prices[name] = price;
int get total => _prices.values.fold(0, (sum, price) => sum + price);
}// test/cart_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:hello_app/cart.dart';
void main() {
group('Cart', () {
test('starts with a total of 0', () {
expect(Cart().total, 0);
});
test('adding items increases the total', () {
final cart = Cart()
..add('apple', 1000)
..add('pear', 2500);
expect(cart.total, 3500);
});
});
}Run tests from the command line or your editor:
# Run all tests
flutter test
# Run a single file
flutter test test/cart_test.dart
# Run tests whose name matches
flutter test --name "total"
# Collect coverage (writes coverage/lcov.info)
flutter test --coverageWidget tests use testWidgets. The WidgetTester mounts a widget (pumpWidget), finds things (find), interacts (tap), rebuilds (pump) and then you assert. The generated test/widget_test.dart is exactly this kind of test:
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hello_app/main.dart';
void main() {
testWidgets('tapping add increments the counter', (WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}Commonly used helpers:
find.text, find.byType, find.byIcon, find.byKey: locate widgets. Giving widgets a key such as Key('submit') makes them easy to find.findsOneWidget, findsNothing, findsNWidgets(n): check how many were foundtester.enterText(finder, 'text'): type into a text fieldtester.pumpAndSettle(): keep pumping frames until animations finishWhen testing code that hits the network, use fake responses instead of a real server. The http package includes a MockClient for tests, so if your function accepts an http.Client, swapping it is easy. For more complex cases, create fakes with mocktail or mockito.
import 'package:http/http.dart' as http;
import 'package:http/testing.dart';
import 'package:flutter_test/flutter_test.dart';
Future<String> fetchTitle(http.Client client) async {
final response = await client.get(Uri.parse('https://example.com/title'));
return response.body;
}
void main() {
test('returns the response body', () async {
final client = MockClient((request) async => http.Response('Flutter', 200));
expect(await fetchTitle(client), 'Flutter');
});
}Integration tests use the integration_test package that comes with the SDK. They launch the app on a real device, emulator or desktop and drive it with the same API as widget tests. First add the dev dependency:
flutter pub add 'dev:integration_test:{"sdk":"flutter"}'Place test files in an integration_test folder at the project root:
// integration_test/app_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:hello_app/main.dart' as app;
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('full app flow', (tester) async {
app.main();
await tester.pumpAndSettle();
await tester.tap(find.byIcon(Icons.add));
await tester.pumpAndSettle();
expect(find.text('1'), findsOneWidget);
});
}# Run on a connected device
flutter test integration_test/app_test.dart
# Pick a device
flutter test integration_test -d windowsflutter test, and add --coverage to collect coverage.pumpWidget, find, tap, pump, expect.
0 Kommentare
Anmelden · Melde dich an, um einen Kommentar zu schreiben.
Schreib den ersten Kommentar.