1. Introduzione
Flutter è il toolkit dell'interfaccia utente di Google che consente di creare fantastiche applicazioni compilate in modo nativo per dispositivi mobili, web e computer a partire da un unico codebase.
In questo codelab, creerai e testerai una semplice app Flutter. L'app utilizzerà il pacchetto Provider per la gestione dello stato.
Obiettivi didattici
- Come creare test dei widget utilizzando il framework di test dei widget
- Come creare un test di integrazione per testare l'UI e le prestazioni dell'app utilizzando la libreria
integration_test
- Come testare le classi di dati (fornitori) con l'aiuto dei test delle unità
Cosa creerai
In questo codelab, inizierai a creare una semplice applicazione con un elenco di elementi. Il codice sorgente ti viene fornito in modo che tu possa passare direttamente al test. L'app supporta le seguenti operazioni:
- Aggiunta degli elementi ai preferiti in corso...
- Visualizzazione dell'elenco dei preferiti
- Rimozione di elementi dall'elenco dei preferiti
Una volta completata l'app, scriverai i seguenti test:
| GIF dell'app in esecuzione su Android |
Cosa ti piacerebbe imparare da questo codelab?
2. Configura l'ambiente di sviluppo di Flutter
Per completare questo lab sono necessari due software: l'SDK Flutter e l'editor.
Puoi eseguire il codelab utilizzando uno di questi dispositivi:
- Un dispositivo fisico Android o iOS connesso al computer e impostato sulla modalità sviluppatore.
- Il simulatore iOS (richiede l'installazione degli strumenti Xcode).
- L'emulatore Android (richiede la configurazione in Android Studio).
- Un browser (per il debug è richiesto Chrome).
- Come applicazione desktop Windows, Linux o macOS. Devi svilupparle sulla piattaforma in cui prevedi di eseguire il deployment. Quindi, se vuoi sviluppare un'app desktop per Windows, devi sviluppare su Windows per accedere alla catena di build appropriata. Alcuni requisiti specifici del sistema operativo sono descritti in dettaglio all'indirizzo docs.flutter.dev/desktop.
3. Per iniziare
Creare una nuova app Flutter e aggiorna le dipendenze
Questo codelab è incentrato sul test di un'app mobile Flutter. Creerai rapidamente l'app da testare utilizzando file di origine che copi e incolli. Il resto del codelab è incentrato sull'apprendimento di diversi tipi di test.
Crea una semplice app Flutter basata su modelli, seguendo le istruzioni riportate in Iniziare a usare la tua prima app Flutter o utilizzando la riga di comando, come mostrato di seguito.
$ flutter create --empty testing_app Creating project testing_app... Resolving dependencies in `testing_app`... Downloading packages... Got dependencies in `testing_app`. Wrote 128 files. All done! You can find general documentation for Flutter at: https://docs.flutter.dev/ Detailed API documentation is available at: https://api.flutter.dev/ If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev In order to run your empty application, type: $ cd testing_app $ flutter run Your empty application code is in testing_app/lib/main.dart.
Aggiungi dipendenze Pub alla riga di comando.
provider
per gestire facilmente lo stato,integration_test
per testare in modo autonomo il codice Flutter su dispositivi ed emulatori,flutter_driver
per un'API avanzata per testare le applicazioni Flutter eseguite su emulatori e dispositivi realitest
per gli strumenti di test generali,go_router
per gestire la navigazione delle app.
$ cd testing_app $ flutter pub add provider go_router dev:test 'dev:flutter_driver:{"sdk":"flutter"}' 'dev:integration_test:{"sdk":"flutter"}' Resolving dependencies... Downloading packages... + _fe_analyzer_shared 67.0.0 (68.0.0 available) + analyzer 6.4.1 (6.5.0 available) + args 2.5.0 + convert 3.1.1 + coverage 1.7.2 + crypto 3.0.3 + file 7.0.0 + flutter_driver 0.0.0 from sdk flutter + flutter_web_plugins 0.0.0 from sdk flutter + frontend_server_client 4.0.0 + fuchsia_remote_debug_protocol 0.0.0 from sdk flutter + glob 2.1.2 + go_router 14.0.2 + http_multi_server 3.2.1 + http_parser 4.0.2 + integration_test 0.0.0 from sdk flutter + io 1.0.4 + js 0.7.1 leak_tracker 10.0.4 (10.0.5 available) leak_tracker_flutter_testing 3.0.3 (3.0.5 available) + logging 1.2.0 material_color_utilities 0.8.0 (0.11.1 available) meta 1.12.0 (1.14.0 available) + mime 1.0.5 + nested 1.0.0 + node_preamble 2.0.2 + package_config 2.1.0 + platform 3.1.4 + pool 1.5.1 + process 5.0.2 + provider 6.1.2 + pub_semver 2.1.4 + shelf 1.4.1 + shelf_packages_handler 3.0.2 + shelf_static 1.1.2 + shelf_web_socket 1.0.4 + source_map_stack_trace 2.1.1 + source_maps 0.10.12 + sync_http 0.3.1 + test 1.25.2 (1.25.4 available) test_api 0.7.0 (0.7.1 available) + test_core 0.6.0 (0.6.2 available) + typed_data 1.3.2 + watcher 1.1.0 + web 0.5.1 + web_socket_channel 2.4.5 + webdriver 3.0.3 + webkit_inspection_protocol 1.2.1 + yaml 3.1.2 Changed 44 dependencies! 9 packages have newer versions incompatible with dependency constraints. Try `flutter pub outdated` for more information.
Le seguenti dipendenze dovrebbero essere state aggiunte a pubspec.yaml:
pubspec.yaml
name: testing_app description: "A new Flutter project." publish_to: 'none' version: 0.1.0 environment: sdk: '>=3.4.0-0 <4.0.0' dependencies: flutter: sdk: flutter go_router: ^14.0.2 provider: ^6.1.2 dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^3.0.0 test: ^1.25.2 flutter_driver: sdk: flutter integration_test: sdk: flutter flutter: uses-material-design: true
Apri il progetto nell'editor di codice che preferisci ed esegui l'app. In alternativa, eseguilo dalla riga di comando come segue.
$ flutter run
4. Crea l'app
Adesso devi creare l'app per testarla. L'app contiene i seguenti file:
lib/models/favorites.dart
: crea la classe del modello per l'elenco dei preferitilib/screens/favorites.dart
: crea il layout per l'elenco dei preferitilib/screens/home.dart
: crea un elenco di elementilib/main.dart
: il file principale in cui viene avviata l'app.
Innanzitutto, crea il modello Favorites
in lib/models/favorites.dart
Crea una nuova directory denominata models
nella directory lib
, quindi crea un nuovo file denominato favorites.dart
. Aggiungi il codice seguente al file:
lib/models/favorites.dart
import 'package:flutter/material.dart';
/// The [Favorites] class holds a list of favorite items saved by the user.
class Favorites extends ChangeNotifier {
final List<int> _favoriteItems = [];
List<int> get items => _favoriteItems;
void add(int itemNo) {
_favoriteItems.add(itemNo);
notifyListeners();
}
void remove(int itemNo) {
_favoriteItems.remove(itemNo);
notifyListeners();
}
}
Aggiungi la pagina Preferiti in lib/screens/favorites.dart
Crea una nuova directory denominata screens
nella directory lib
e in quella directory crea un nuovo file denominato favorites.dart
. Aggiungi il codice seguente al file:
lib/screens/favorites.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/favorites.dart';
class FavoritesPage extends StatelessWidget {
const FavoritesPage({super.key});
static String routeName = 'favorites_page';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Favorites'),
),
body: Consumer<Favorites>(
builder: (context, value, child) => ListView.builder(
itemCount: value.items.length,
padding: const EdgeInsets.symmetric(vertical: 16),
itemBuilder: (context, index) => FavoriteItemTile(value.items[index]),
),
),
);
}
}
class FavoriteItemTile extends StatelessWidget {
const FavoriteItemTile(this.itemNo, {super.key});
final int itemNo;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.primaries[itemNo % Colors.primaries.length],
),
title: Text(
'Item $itemNo',
key: Key('favorites_text_$itemNo'),
),
trailing: IconButton(
key: Key('remove_icon_$itemNo'),
icon: const Icon(Icons.close),
onPressed: () {
Provider.of<Favorites>(context, listen: false).remove(itemNo);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Removed from favorites.'),
duration: Duration(seconds: 1),
),
);
},
),
),
);
}
}
Aggiungi la home page in lib/screens/home.dart
Nella directory lib/screens
crea un altro nuovo file denominato home.dart
. In lib/screens/home.dart
, aggiungi il seguente codice:
lib/screens/home.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import '../models/favorites.dart';
import 'favorites.dart';
class HomePage extends StatelessWidget {
static String routeName = '/';
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Testing Sample'),
actions: <Widget>[
TextButton.icon(
onPressed: () {
context.go('/${FavoritesPage.routeName}');
},
icon: const Icon(Icons.favorite_border),
label: const Text('Favorites'),
),
],
),
body: ListView.builder(
itemCount: 100,
cacheExtent: 20.0,
padding: const EdgeInsets.symmetric(vertical: 16),
itemBuilder: (context, index) => ItemTile(index),
),
);
}
}
class ItemTile extends StatelessWidget {
final int itemNo;
const ItemTile(this.itemNo, {super.key});
@override
Widget build(BuildContext context) {
var favoritesList = Provider.of<Favorites>(context);
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.primaries[itemNo % Colors.primaries.length],
),
title: Text(
'Item $itemNo',
key: Key('text_$itemNo'),
),
trailing: IconButton(
key: Key('icon_$itemNo'),
icon: favoritesList.items.contains(itemNo)
? const Icon(Icons.favorite)
: const Icon(Icons.favorite_border),
onPressed: () {
!favoritesList.items.contains(itemNo)
? favoritesList.add(itemNo)
: favoritesList.remove(itemNo);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(favoritesList.items.contains(itemNo)
? 'Added to favorites.'
: 'Removed from favorites.'),
duration: const Duration(seconds: 1),
),
);
},
),
),
);
}
}
Sostituisci i contenuti di lib/main.dart
Sostituisci i contenuti di lib/main.dart
con il seguente codice:
lib/main.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'models/favorites.dart';
import 'screens/favorites.dart';
import 'screens/home.dart';
void main() {
runApp(const TestingApp());
}
final _router = GoRouter(
routes: [
GoRoute(
path: HomePage.routeName,
builder: (context, state) {
return const HomePage();
},
routes: [
GoRoute(
path: FavoritesPage.routeName,
builder: (context, state) {
return const FavoritesPage();
},
),
],
),
],
);
class TestingApp extends StatelessWidget {
const TestingApp({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Favorites>(
create: (context) => Favorites(),
child: MaterialApp.router(
title: 'Testing Sample',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
),
useMaterial3: true,
),
routerConfig: _router,
),
);
}
}
Ora l'app è completa, ma non è stata testata.
Esegui l'app. Dovrebbe essere simile al seguente screenshot:
L'app mostra un elenco di elementi. Tocca l'icona a forma di cuore su una riga qualsiasi per riempire il cuore e aggiungere l'elemento all'elenco dei preferiti. Il pulsante Preferiti su AppBar
ti porta a una seconda schermata contenente l'elenco dei preferiti.
L'app è ora pronta per i test. Inizierai a testare l'app nel passaggio successivo.
5. Test delle unità del provider
Inizierai eseguendo il test delle unità del modello favorites
. Che cos'è un test delle unità? Un test delle unità verifica che ogni singola unità del software, che si tratti di una funzione, di un oggetto o di un widget, esegue correttamente l'attività prevista.
Tutti i file di test in un'app Flutter, ad eccezione dei test di integrazione, vengono inseriti nella directory test
.
Rimuovi test/widget_test.dart
Prima di iniziare il test, elimina il file widget_test.dart
. Aggiungerai i tuoi file di test.
Crea un nuovo file di test
Innanzitutto, testerai il metodo add()
nel modello Favorites
per verificare che un nuovo elemento venga aggiunto all'elenco e che l'elenco rifletta la modifica. Per convenzione, la struttura di directory nella directory test
riproduce il nome della directory lib
e dei file Dart, con l'aggiunta di _test
.
Crea una directory models
nella directory test
. In questa nuova directory, crea un file favorites_test.dart
con i seguenti contenuti:
test/models/favorites_test.dart
import 'package:test/test.dart';
import 'package:testing_app/models/favorites.dart';
void main() {
group('Testing App Provider', () {
var favorites = Favorites();
test('A new item should be added', () {
var number = 35;
favorites.add(number);
expect(favorites.items.contains(number), true);
});
});
}
Il framework di test Flutter ti consente di associare test simili correlati tra loro in un gruppo. Un singolo file di test può contenere più gruppi con lo scopo di testare diverse parti del file corrispondente nella directory lib
.
Il metodo test()
accetta due parametri posizionali: description
del test e callback
in cui scrivi effettivamente il test.
Prova a rimuovere un elemento dall'elenco. Inserisci il seguente test nello stesso gruppo Testing App Provider
:
test/models/favorites_test.dart
test('An item should be removed', () {
var number = 45;
favorites.add(number);
expect(favorites.items.contains(number), true);
favorites.remove(number);
expect(favorites.items.contains(number), false);
});
Eseguire il test
Nella riga di comando, vai alla directory principale del progetto e inserisci questo comando:
$ flutter test test/models/favorites_test.dart
Se tutto funziona correttamente, dovresti vedere un messaggio simile al seguente:
00:06 +2: All tests passed!
Il file di test completo: test/models/favorites_test.dart
.
Per ulteriori informazioni sui test delle unità, consulta Introduzione ai test delle unità.
6. Test dei widget
In questo passaggio aggiungerai codice per testare i widget. Il test dei widget è un'esclusiva di Flutter, che consente di testare ogni widget in modo isolato. Questo passaggio verifica le schermate HomePage
e FavoritesPage
singolarmente.
Il test del widget utilizza la funzione testWidget()
anziché la funzione test()
. Come la funzione test()
, la funzione testWidget()
accetta due parametri: description,
e callback
, ma il callback utilizza WidgetTester
come argomento.
I test dei widget utilizzano TestFlutterWidgetsBinding
, una classe che fornisce ai tuoi widget le stesse risorse che avrebbero in un'app in esecuzione, ad esempio informazioni sulle dimensioni dello schermo e sulla possibilità di pianificare le animazioni, ma senza eseguire l'operazione all'interno di un'app. Viene invece utilizzato un ambiente virtuale per creare un'istanza del widget e testare i risultati. In questo caso, pumpWidget
avvia il processo dicendo al framework di montare e misurare un determinato widget proprio come farebbe in un'applicazione.
Il framework di test del widget fornisce agli utenti che trovano widget, ad esempio text()
, byType()
e byIcon().
. Inoltre, fornisce matcher per verificare i risultati.
Inizia provando il widget HomePage
.
Crea un nuovo file di test
Il primo test verifica se lo scorrimento di HomePage
funziona correttamente.
Crea un nuovo file nella directory test
e assegnagli il nome home_test.dart
. Nel file appena creato, aggiungi il codice seguente:
test/home_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';
import 'package:testing_app/models/favorites.dart';
import 'package:testing_app/screens/home.dart';
Widget createHomeScreen() => ChangeNotifierProvider<Favorites>(
create: (context) => Favorites(),
child: const MaterialApp(
home: HomePage(),
),
);
void main() {
group('Home Page Widget Tests', () {
testWidgets('Testing Scrolling', (tester) async {
await tester.pumpWidget(createHomeScreen());
expect(find.text('Item 0'), findsOneWidget);
await tester.fling(
find.byType(ListView),
const Offset(0, -200),
3000,
);
await tester.pumpAndSettle();
expect(find.text('Item 0'), findsNothing);
});
});
}
La funzione createHomeScreen()
viene utilizzata per creare un'app che carica il widget da testare in un MaterialApp, aggregato in un ChangeNotifierProvider. Il widget della home page richiede che entrambi questi widget siano presenti sopra nella struttura ad albero dei widget, in modo che possa ereditare da questi e ottenere l'accesso ai dati che offrono. Questa funzione viene passata come parametro alla funzione pumpWidget()
.
Ora verifica se il framework riesce a trovare un ListView
visualizzato sullo schermo.
Aggiungi il seguente snippet di codice a home_test.dart
:
test/home_test.dart
group('Home Page Widget Tests', () {
// BEGINNING OF NEW CONTENT
testWidgets('Testing if ListView shows up', (tester) async {
await tester.pumpWidget(createHomeScreen());
expect(find.byType(ListView), findsOneWidget);
});
// END OF NEW CONTENT
testWidgets('Testing Scrolling', (tester) async {
await tester.pumpWidget(createHomeScreen());
expect(find.text('Item 0'), findsOneWidget);
await tester.fling(
find.byType(ListView),
const Offset(0, -200),
3000,
);
await tester.pumpAndSettle();
expect(find.text('Item 0'), findsNothing);
});
});
Eseguire il test
Per prima cosa, esegui il test nello stesso modo in cui eseguiresti un test delle unità, con il comando:
$ flutter test test/home_test.dart
Il test dovrebbe essere eseguito rapidamente e dovresti visualizzare un messaggio simile al seguente:
00:02 +2: All tests passed!
Puoi anche eseguire test del widget utilizzando un dispositivo o un emulatore, che ti consente di osservare l'esecuzione del test. Inoltre, ti offre la possibilità di utilizzare il riavvio a caldo.
Collega il dispositivo o avvia l'emulatore. Puoi anche eseguire il test come applicazione desktop.
Dalla riga di comando, vai alla directory principale del progetto e inserisci questo comando:
$ flutter run test/home_test.dart
Potresti dover selezionare il dispositivo su cui eseguire il test. In questo caso, segui le istruzioni e seleziona un dispositivo:
Multiple devices found:
Linux (desktop) • linux • linux-x64 • Ubuntu 22.04.1 LTS 5.15.0-58-generic
Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119
[1]: Linux (linux)
[2]: Chrome (chrome)
Please choose one (To quit, press "q/Q"):
Se tutto funziona, dovresti vedere un output simile al seguente:
Launching test/home_test.dart on Linux in debug mode...
Building Linux application...
flutter: 00:00 +0: Home Page Widget Tests Testing if ListView shows up
Syncing files to device Linux... 62ms
Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).
💪 Running with sound null safety 💪
An Observatory debugger and profiler on Linux is available at: http://127.0.0.1:35583/GCpdLBqf2UI=/
flutter: 00:00 +1: Home Page Widget Tests Testing Scrolling
The Flutter DevTools debugger and profiler on Linux is available at:
http://127.0.0.1:9100?uri=http://127.0.0.1:35583/GCpdLBqf2UI=/
flutter: 00:02 +2: All tests passed!
Successivamente, apporterai le modifiche al file di test e premi Shift + R
per riavviare l'app a caldo e ripetere tutti i test. Non arrestare l'applicazione.
Aggiungi altri test al gruppo che verifica i widget della home page. Copia il seguente test nel tuo file:
test/home_test.dart
testWidgets('Testing IconButtons', (tester) async {
await tester.pumpWidget(createHomeScreen());
expect(find.byIcon(Icons.favorite), findsNothing);
await tester.tap(find.byIcon(Icons.favorite_border).first);
await tester.pumpAndSettle(const Duration(seconds: 1));
expect(find.text('Added to favorites.'), findsOneWidget);
expect(find.byIcon(Icons.favorite), findsWidgets);
await tester.tap(find.byIcon(Icons.favorite).first);
await tester.pumpAndSettle(const Duration(seconds: 1));
expect(find.text('Removed from favorites.'), findsOneWidget);
expect(find.byIcon(Icons.favorite), findsNothing);
});
Questo test verifica che il tocco del IconButton
passi da Icons.favorite_border
(un cuore aperto) a Icons.favorite
(un cuore pieno) e poi di nuovo a Icons.favorite_border
quando viene toccato di nuovo.
Inserisci Shift + R
. Questo aggiornamento rapido riavvia l'app ed esegue nuovamente tutti i test.
Il file di test completo: test/home_test.dart
.
Usa la stessa procedura per testare FavoritesPage
con il codice che segue. Segui gli stessi passaggi ed eseguilo.
test/Favorites_test.ARROW
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';
import 'package:testing_app/models/favorites.dart';
import 'package:testing_app/screens/favorites.dart';
late Favorites favoritesList;
Widget createFavoritesScreen() => ChangeNotifierProvider<Favorites>(
create: (context) {
favoritesList = Favorites();
return favoritesList;
},
child: const MaterialApp(
home: FavoritesPage(),
),
);
void addItems() {
for (var i = 0; i < 10; i += 2) {
favoritesList.add(i);
}
}
void main() {
group('Favorites Page Widget Tests', () {
testWidgets('Test if ListView shows up', (tester) async {
await tester.pumpWidget(createFavoritesScreen());
addItems();
await tester.pumpAndSettle();
expect(find.byType(ListView), findsOneWidget);
});
testWidgets('Testing Remove Button', (tester) async {
await tester.pumpWidget(createFavoritesScreen());
addItems();
await tester.pumpAndSettle();
var totalItems = tester.widgetList(find.byIcon(Icons.close)).length;
await tester.tap(find.byIcon(Icons.close).first);
await tester.pumpAndSettle();
expect(tester.widgetList(find.byIcon(Icons.close)).length,
lessThan(totalItems));
expect(find.text('Removed from favorites.'), findsOneWidget);
});
});
}
Questo test verifica se un elemento scompare quando viene premuto il pulsante di chiusura (rimozione).
Per ulteriori informazioni sul test del widget, visita:
7. Test dell'interfaccia utente dell'app con test di integrazione
I test di integrazione vengono utilizzati per verificare l'interazione tra le singole parti di un'app. La libreria integration_test
viene utilizzata per eseguire i test di integrazione in Flutter. Questa è la versione di Flutter di Selenium WebDriver, Goniometro, Espresso o Earl Gray. Il pacchetto utilizza internamente flutter_driver
per eseguire il test su un dispositivo.
Scrivere test di integrazione in Flutter è simile alla scrittura di test widget, ad eccezione del fatto che i test di integrazione vengono eseguiti su un dispositivo mobile, un browser o un'applicazione desktop, chiamato dispositivo di destinazione.
Scrivi il test
Crea una directory denominata integration_test
nella directory radice del progetto e in quella directory crea un nuovo file denominato app_test.dart
.
integration_test/app_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:testing_app/main.dart';
void main() {
group('Testing App', () {
testWidgets('Favorites operations test', (tester) async {
await tester.pumpWidget(const TestingApp());
final iconKeys = [
'icon_0',
'icon_1',
'icon_2',
];
for (var icon in iconKeys) {
await tester.tap(find.byKey(ValueKey(icon)));
await tester.pumpAndSettle(const Duration(seconds: 1));
expect(find.text('Added to favorites.'), findsOneWidget);
}
await tester.tap(find.text('Favorites'));
await tester.pumpAndSettle();
final removeIconKeys = [
'remove_icon_0',
'remove_icon_1',
'remove_icon_2',
];
for (final iconKey in removeIconKeys) {
await tester.tap(find.byKey(ValueKey(iconKey)));
await tester.pumpAndSettle(const Duration(seconds: 1));
expect(find.text('Removed from favorites.'), findsOneWidget);
}
});
});
}
Eseguire il test
Collega il dispositivo o avvia l'emulatore. Puoi anche eseguire il test come applicazione desktop.
Nella riga di comando, vai alla directory principale del progetto e inserisci questo comando:
$ flutter test integration_test/app_test.dart
Se tutto funziona, dovresti vedere un output simile al seguente:
Multiple devices found:
Linux (desktop) • linux • linux-x64 • Ubuntu 22.04.1 LTS 5.15.0-58-generic
Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119
[1]: Linux (linux)
[2]: Chrome (chrome)
Please choose one (To quit, press "q/Q"): 1
00:00 +0: loading /home/miquel/tmp/testing_app/integration_test/app_test.dart B00:08 +0: loading /home/miquel/tmp/testing_app/integration_test/app_test.dart
00:26 +1: All tests passed!
8. Testare le prestazioni dell'app con Flutter Driver
Scrivere un test delle prestazioni
Crea un nuovo file di test denominato perf_test.arrow nella cartella integration_test con il contenuto seguente:
integration_test/perf_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:testing_app/main.dart';
void main() {
group('Testing App Performance', () {
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
testWidgets('Scrolling test', (tester) async {
await tester.pumpWidget(const TestingApp());
final listFinder = find.byType(ListView);
await binding.traceAction(() async {
await tester.fling(listFinder, const Offset(0, -500), 10000);
await tester.pumpAndSettle();
await tester.fling(listFinder, const Offset(0, 500), 10000);
await tester.pumpAndSettle();
}, reportKey: 'scrolling_summary');
});
});
}
La funzione ensureInitialized()
verifica se il driver del test di integrazione è stato inizializzato, reinizializzandolo se necessario. Impostare il valore framePolicy
su fullyLive
è ideale per testare il codice animato.
Questo test scorre molto velocemente l'elenco di elementi e poi scorre completamente verso l'alto. La funzione traceAction()
registra le azioni e genera un riepilogo della sequenza temporale.
Acquisisci i risultati sul rendimento
Per acquisire i risultati, crea una cartella denominata test_driver
con un file denominato perf_driver.dart
e aggiungi il codice seguente:
test_driver/perf_driver.arrow
import 'package:flutter_driver/flutter_driver.dart' as driver;
import 'package:integration_test/integration_test_driver.dart';
Future<void> main() {
return integrationDriver(
responseDataCallback: (data) async {
if (data != null) {
final timeline = driver.Timeline.fromJson(
data['scrolling_summary'] as Map<String, dynamic>);
final summary = driver.TimelineSummary.summarize(timeline);
await summary.writeTimelineToFile(
'scrolling_summary',
pretty: true,
includeSummary: true,
);
}
},
);
}
Eseguire il test
Collega il dispositivo o avvia l'emulatore.
Nella riga di comando, vai alla directory principale del progetto e inserisci questo comando:
$ flutter drive \
--driver=test_driver/perf_driver.dart \
--target=integration_test/perf_test.dart \
--profile \
--no-dds
Se tutto funziona, dovresti vedere un output simile al seguente:
Running "flutter pub get" in testing_app...
Resolving dependencies...
archive 3.3.2 (3.3.6 available)
collection 1.17.0 (1.17.1 available)
js 0.6.5 (0.6.7 available)
matcher 0.12.13 (0.12.14 available)
meta 1.8.0 (1.9.0 available)
path 1.8.2 (1.8.3 available)
test 1.22.0 (1.23.0 available)
test_api 0.4.16 (0.4.18 available)
test_core 0.4.20 (0.4.23 available)
vm_service 9.4.0 (11.0.1 available)
webdriver 3.0.1 (3.0.2 available)
Got dependencies!
Running Gradle task 'assembleProfile'... 1,379ms
✓ Built build/app/outputs/flutter-apk/app-profile.apk (14.9MB).
Installing build/app/outputs/flutter-apk/app-profile.apk... 222ms
I/flutter ( 6125): 00:04 +1: Testing App Performance (tearDownAll)
I/flutter ( 6125): 00:04 +2: All tests passed!
All tests passed.
Al termine del test, la directory di compilazione alla radice del progetto contiene due file:
scrolling_summary.timeline_summary.json
contiene il riepilogo. Apri il file con qualsiasi editor di testo per esaminare le informazioni al suo interno.scrolling_summary.timeline.json
contiene i dati completi della sequenza temporale.
Per maggiori dettagli sui test di integrazione, visita:
9. Complimenti!
Hai completato il codelab e hai imparato diversi modi per testare un'app Flutter.
Che cosa hai imparato
- Come testare i fornitori con l'aiuto dei test delle unità
- Come testare i widget utilizzando il framework di test dei widget
- Come testare l'UI dell'app utilizzando i test di integrazione
- Come testare le prestazioni dell'app utilizzando i test di integrazione
Per scoprire di più sui test in Flutter, visita