Les proves de widgets són una part essencial del desenvolupament d'aplicacions en Flutter. Aquest tipus de proves permeten verificar que els widgets es comporten com s'espera en diferents situacions. En aquesta secció, aprendrem com crear i executar proves de widgets per assegurar-nos que la nostra interfície d'usuari funcioni correctament.
Objectius d'Aprenentatge
- Comprendre la importància de les proves de widgets.
- Aprendre a configurar un entorn de proves de widgets.
- Escriure i executar proves de widgets bàsiques.
- Utilitzar
WidgetTester
per interactuar amb els widgets durant les proves.
- Importància de les Proves de Widgets
Les proves de widgets són crucials per diverses raons:
- Verificació de la UI: Asseguren que la interfície d'usuari es mostri correctament.
- Detecció de Regressions: Identifiquen canvis no desitjats en la UI després de modificacions en el codi.
- Automatització: Permeten automatitzar la verificació de la funcionalitat de la UI, estalviant temps i esforç.
- Configuració de l'Entorn de Proves
Abans de començar a escriure proves de widgets, necessitem configurar l'entorn de proves. Flutter proporciona un paquet de proves integrat que facilita aquesta tasca.
Passos per Configurar l'Entorn de Proves
-
Afegir el paquet de proves: Assegura't que el paquet
flutter_test
estigui inclòs en el fitxerpubspec.yaml
:dev_dependencies: flutter_test: sdk: flutter
-
Crear un fitxer de proves: Crea un fitxer nou dins del directori
test/
. Per exemple,test/widget_test.dart
.
- Escriure una Prova de Widget Bàsica
A continuació, escriurem una prova de widget bàsica per verificar que un widget es mostra correctament.
Exemple de Prova de Widget
Suposem que tenim un widget senzill que mostra un text "Hola, món!".
Codi del Widget
import 'package:flutter/material.dart'; class MyWidget extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: Text('Hola, món!'), ), ), ); } }
Codi de la Prova
import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:my_app/my_widget.dart'; // Assegura't d'importar el widget correcte void main() { testWidgets('MyWidget mostra el text "Hola, món!"', (WidgetTester tester) async { // Construir el widget dins del tester await tester.pumpWidget(MyWidget()); // Verificar que el text "Hola, món!" es mostri en pantalla expect(find.text('Hola, món!'), findsOneWidget); }); }
Explicació del Codi de la Prova
testWidgets
: Defineix una prova de widget. Accepta una descripció de la prova i una funció que conté el codi de la prova.WidgetTester
: Proporciona mètodes per interactuar amb els widgets durant la prova.pumpWidget
: Construeix el widget dins del tester.find.text
: Cerca un widget de text amb el contingut especificat.expect
: Verifica que la condició especificada sigui certa. En aquest cas, que hi hagi exactament un widget amb el text "Hola, món!".
- Utilitzar
WidgetTester
per Interactuar amb Widgets
WidgetTester
per Interactuar amb WidgetsEl WidgetTester
proporciona diverses funcions per interactuar amb els widgets durant les proves. A continuació, veurem alguns exemples comuns.
Exemple: Prova d'un Botó
Suposem que tenim un widget amb un botó que incrementa un comptador.
Codi del Widget
import 'package:flutter/material.dart'; class CounterWidget extends StatefulWidget { @override _CounterWidgetState createState() => _CounterWidgetState(); } class _CounterWidgetState extends State<CounterWidget> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Counter')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('$_counter', key: Key('counter')), ElevatedButton( onPressed: _incrementCounter, child: Text('Incrementar'), ), ], ), ), ), ); } }
Codi de la Prova
import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:my_app/counter_widget.dart'; // Assegura't d'importar el widget correcte void main() { testWidgets('CounterWidget incrementa el comptador quan es prem el botó', (WidgetTester tester) async { // Construir el widget dins del tester await tester.pumpWidget(CounterWidget()); // Verificar que el comptador inicialment és 0 expect(find.text('0'), findsOneWidget); // Prem el botó await tester.tap(find.byType(ElevatedButton)); await tester.pump(); // Re-dibuixar el widget després de l'acció // Verificar que el comptador ha incrementat a 1 expect(find.text('1'), findsOneWidget); }); }
Explicació del Codi de la Prova
tap
: Simula un toc en el widget especificat.pump
: Re-dibuixa el widget després d'una acció, permetent que els canvis es reflecteixin en la UI.
Exercicis Pràctics
- Prova de TextField: Escriu una prova per verificar que un
TextField
accepta i mostra correctament el text introduït per l'usuari. - Prova de Checkbox: Escriu una prova per verificar que un
Checkbox
canvia el seu estat quan es prem.
Solucions
Prova de TextField
testWidgets('TextField accepta i mostra el text introduït', (WidgetTester tester) async { // Construir el widget amb un TextField await tester.pumpWidget(MaterialApp( home: Scaffold( body: TextField(key: Key('textField')), ), )); // Introduir text al TextField await tester.enterText(find.byKey(Key('textField')), 'Hola Flutter'); await tester.pump(); // Verificar que el TextField mostra el text introduït expect(find.text('Hola Flutter'), findsOneWidget); });
Prova de Checkbox
testWidgets('Checkbox canvia el seu estat quan es prem', (WidgetTester tester) async { bool isChecked = false; // Construir el widget amb un Checkbox await tester.pumpWidget(MaterialApp( home: Scaffold( body: StatefulBuilder( builder: (BuildContext context, StateSetter setState) { return Checkbox( value: isChecked, onChanged: (bool? value) { setState(() { isChecked = value!; }); }, ); }, ), ), )); // Verificar que el Checkbox inicialment no està seleccionat expect(find.byType(Checkbox), findsOneWidget); expect((tester.widget(find.byType(Checkbox)) as Checkbox).value, false); // Prem el Checkbox await tester.tap(find.byType(Checkbox)); await tester.pump(); // Verificar que el Checkbox està seleccionat expect((tester.widget(find.byType(Checkbox)) as Checkbox).value, true); });
Conclusió
Les proves de widgets són una eina poderosa per assegurar la qualitat de la interfície d'usuari en aplicacions Flutter. Hem après a configurar l'entorn de proves, escriure proves de widgets bàsiques i utilitzar WidgetTester
per interactuar amb els widgets. Amb aquestes habilitats, estem preparats per crear aplicacions més robustes i fiables.
Curs de Desenvolupament Flutter
Mòdul 1: Introducció a Flutter
- Què és Flutter?
- Configuració de l'Entorn de Desenvolupament
- Comprensió de l'Arquitectura de Flutter
- Creació de la Teva Primera Aplicació Flutter
Mòdul 2: Conceptes Bàsics de Programació en Dart
- Introducció a Dart
- Variables i Tipus de Dades
- Sentències de Flux de Control
- Funcions i Mètodes
- Programació Orientada a Objectes en Dart
Mòdul 3: Widgets de Flutter
- Introducció als Widgets
- Widgets Stateless vs Stateful
- Widgets Bàsics
- Widgets de Disseny
- Widgets d'Entrada i Formulari
Mòdul 4: Gestió de l'Estat
Mòdul 5: Navegació i Enrutament
- Introducció a la Navegació
- Navegació Bàsica
- Rutes Nomenades
- Passar Dades Entre Pantalles
- Deep Linking
Mòdul 6: Xarxes i APIs
- Obtenir Dades d'Internet
- Analitzar Dades JSON
- Gestió d'Errors de Xarxa
- Ús d'APIs REST
- Integració de GraphQL
Mòdul 7: Persistència i Emmagatzematge
- Introducció a la Persistència
- Preferències Compartides
- Emmagatzematge de Fitxers
- Base de Dades SQLite
- Ús de Hive per a l'Emmagatzematge Local
Mòdul 8: Conceptes Avançats de Flutter
- Animacions en Flutter
- Pintura Personalitzada i Canvas
- Canals de Plataforma
- Isolates i Concurrència
- Optimització del Rendiment
Mòdul 9: Proves i Depuració
- Introducció a les Proves
- Proves Unitàries
- Proves de Widgets
- Proves d'Integració
- Tècniques de Depuració
Mòdul 10: Desplegament i Manteniment
- Preparació per al Llançament
- Construcció per a iOS
- Construcció per a Android
- Integració i Desplegament Continu (CI/CD)
- Manteniment i Actualització de la Teva Aplicació