Testen von Dart- und Flutter-Anwendungen
Inhalt
- Strukturierung von Testdateien
- Schreiben von Tests
- Ausführen von Tests
- Workflow zur Testimplementierung
- Beispiele
Strukturierung von Testdateien
Organisiere Testdateien spiegelbildlich zur lib-Verzeichnisstruktur, um Vorhersagbarkeit zu gewährleisten.
- Platziere den gesamten Testcode im
test-Verzeichnis auf der obersten Ebene des Pakets. - Füge
_test.dartan das Ende aller Testdateinamen an (z.B.lib/src/utils.dartsollte intest/src/utils_test.dartgetestet werden). - Wenn du Integrationstests schreibst, platziere sie in einem
integration_test-Verzeichnis auf der obersten Ebene des Pakets.
Schreiben von Tests
Verwende package:test als Standard-Testbibliothek für Dart-Anwendungen.
- Importiere
package:test/test.dart(oderpackage:flutter_test/flutter_test.dartfür Flutter). - Gruppiere verwandte Tests mit der
group()-Funktion, um einen gemeinsamen Kontext bereitzustellen. - Definiere einzelne Testfälle mit der
test()-Funktion. - Validiere Ergebnisse mit der
expect()-Funktion zusammen mit Matchern (z.B.equals(),isTrue,throwsA()). - Schreibe asynchrone Tests mit der standardmäßigen
async/await-Syntax. Der Testrunner wartet automatisch auf den Abschluss desFuture. - Verwalte Test-Setup und -Teardown mit
setUp()- undtearDown()-Callbacks. - Wenn Code getestet wird, der auf Abhängigkeitsinjektion angewiesen ist, verwende
package:mockitozusammen mitpackage:test, um Mock-Objekte zu generieren, festgelegte Szenarien zu konfigurieren und Interaktionen zu überprüfen.
Ausführen von Tests
Wähle den passenden Testrunner basierend auf dem Projekttyp und dem Speicherort der Tests aus.
- Wenn du an einem reinen Dart-Projekt arbeitest, führe die Tests mit dem Befehl
dart testaus. - Wenn du an einem Flutter-Projekt arbeitest, führe die Tests mit dem Befehl
flutter testaus. - Wenn du Integrationstests ausführst, gib explizit den Verzeichnispfad an, da der Standard-Runner ihn ignoriert:
dart test integration_testoderflutter test integration_test.
Workflow zur Testimplementierung
Befolge diesen sequenziellen Workflow bei der Implementierung neuer Test-Suiten. Kopiere die Checkliste, um deinen Fortschritt zu verfolgen.
Aufgabenfortschritt
- 1. Erstelle die Testdatei im Verzeichnis
test/und stelle sicher, dass das Suffix_test.dartvorhanden ist. - 2. Importiere
package:test/test.dartund die Ziellibrary. - 3. Definiere eine
main()-Funktion. - 4. Initialisiere gemeinsame Ressourcen oder Mocks mit
setUp(). - 5. Schreibe
test()-Fälle, gruppiert nach Funktionalität mitgroup(). - 6. Führe die Test-Suite mit dem entsprechenden CLI-Befehl aus.
- 7. Feedback-Schleife: Test ausführen → Stacktrace auf Fehler überprüfen → Implementierung oder Assertions korrigieren → Erneut ausführen, bis der Test bestanden wird.
Beispiele
Standard-Komponententest-Suite
Zeigt Gruppierung, Setup, synchrones und asynchrones Testen.
import 'package:test/test.dart';
import 'package:my_package/calculator.dart';
void main() {
group('Calculator', () {
late Calculator calc;
setUp(() {
calc = Calculator();
});
test('adds two numbers correctly', () {
expect(calc.add(2, 3), equals(5));
});
test('handles asynchronous operations', () async {
final result = await calc.fetchRemoteValue();
expect(result, isNotNull);
expect(result, greaterThan(0));
});
});
}
Mocking mit Mockito
Zeigt das Konfigurieren eines Mock-Objekts für das Testen von Abhängigkeitsinjektionen.
import 'package:test/test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
import 'package:my_package/api_client.dart';
import 'package:my_package/data_service.dart';
// Generiere den Mock mit build_runner: dart run build_runner build
@GenerateNiceMocks([MockSpec<ApiClient>()])
import 'data_service_test.mocks.dart';
void main() {
group('DataService', () {
late MockApiClient mockApiClient;
late DataService dataService;
setUp(() {
mockApiClient = MockApiClient();
dataService = DataService(apiClient: mockApiClient);
});
test('returns parsed data on successful API call', () async {
// Konfiguriere den Mock
when(mockApiClient.get('/data')).thenAnswer((_) async => '{"id": 1}');
// Führe das zu testende System aus
final result = await dataService.fetchData();
// Überprüfe Ergebnisse und Interaktionen
expect(result.id, equals(1));
verify(mockApiClient.get('/data')).called(1);
});
});
}