1. Pengantar
Flutter adalah toolkit UI Google untuk membangun aplikasi yang menarik dan dikompilasi secara native dari satu codebase untuk perangkat seluler, web, dan desktop.
Di codelab ini, Anda akan mem-build dan menguji aplikasi Flutter sederhana. Aplikasi akan menggunakan paket Provider untuk mengelola status.
Yang akan Anda pelajari
- Cara membuat pengujian widget menggunakan framework pengujian widget
- Cara membuat pengujian integrasi untuk menguji performa dan UI aplikasi menggunakan library
integration_test
- Cara menguji class data (penyedia) dengan bantuan pengujian unit
Yang akan Anda bangun
Di codelab ini, Anda akan mulai mem-build aplikasi sederhana dengan daftar item. Kami menyediakan kode sumber bagi Anda sehingga Anda dapat langsung ke pengujian. Aplikasi ini mendukung operasi berikut:
- Menambahkan item ke favorit
- Melihat daftar favorit
- Menghapus item dari daftar favorit
Setelah aplikasi selesai, Anda akan menulis pengujian berikut:
| GIF aplikasi yang berjalan di Android |
Apa yang ingin Anda pelajari dari codelab ini?
2. Menyiapkan lingkungan pengembangan Flutter Anda
Anda memerlukan dua software untuk menyelesaikan lab ini—Flutter SDK dan editor.
Anda dapat menjalankan codelab menggunakan salah satu perangkat berikut:
- Perangkat Android atau iOS fisik yang terhubung ke komputer dan disetel ke Mode developer.
- Simulator iOS (perlu menginstal alat Xcode).
- Android Emulator (perlu penyiapan di Android Studio).
- Browser (perlu Chrome untuk proses debug).
- Aplikasi desktop Windows, Linux, atau macOS. Anda harus mengembangkan aplikasi di platform tempat Anda berencana untuk men-deploy-nya. Jadi, jika ingin mengembangkan aplikasi desktop Windows, Anda harus mengembangkannya di Windows untuk mengakses rantai build yang sesuai. Ada persyaratan spesifik per sistem operasi yang dibahas secara mendetail di docs.flutter.dev/desktop.
3. Memulai
Membuat dependensi update dan aplikasi Flutter baru
Codelab ini berfokus untuk menguji aplikasi seluler Flutter. Anda dapat dengan cepat membuat aplikasi yang akan diuji menggunakan file sumber yang Anda salin dan tempel. Kemudian, bagian codelab lainnya berfokus untuk mempelajari berbagai jenis pengujian.
Buat aplikasi Flutter dengan template sederhana menggunakan petunjuk di Memulai aplikasi Flutter pertama Anda, atau di command line sebagai berikut.
$ flutter create testing_app
Tambahkan dependensi pub di command line. Untuk memudahkan pengelolaan status, tambahkan provider
:
$ cd testing_app $ flutter pub add provider Resolving dependencies... 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) + nested 1.0.0 path 1.8.2 (1.8.3 available) + provider 6.0.5 test_api 0.4.16 (0.4.18 available) Changed 2 dependencies!
Untuk pengujian kode Flutter secara otomatis di perangkat dan emulator, tambahkan integration_test
:
$ flutter pub add --dev --sdk=flutter integration_test Resolving dependencies... + archive 3.3.2 (3.3.6 available) collection 1.17.0 (1.17.1 available) + crypto 3.0.2 + file 6.1.4 + flutter_driver 0.0.0 from sdk flutter + fuchsia_remote_debug_protocol 0.0.0 from sdk flutter + integration_test 0.0.0 from sdk flutter 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) + platform 3.1.0 + process 4.2.4 + sync_http 0.3.1 test_api 0.4.16 (0.4.18 available) + typed_data 1.3.1 + vm_service 9.4.0 (11.0.1 available) + webdriver 3.0.1 (3.0.2 available) Changed 12 dependencies!
Untuk API tingkat lanjut guna menguji aplikasi Flutter yang berjalan di perangkat dan emulator sungguhan, tambahkan flutter_driver
:
$ flutter pub add --dev --sdk=flutter flutter_driver 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_api 0.4.16 (0.4.18 available) vm_service 9.4.0 (11.0.1 available) webdriver 3.0.1 (3.0.2 available) Got dependencies!
Untuk alat pengujian umum, tambahkan test
:
$ flutter pub add --dev test Resolving dependencies... + _fe_analyzer_shared 52.0.0 + analyzer 5.4.0 archive 3.3.2 (3.3.6 available) + args 2.3.2 collection 1.17.0 (1.17.1 available) + convert 3.1.1 + coverage 1.6.3 + frontend_server_client 3.2.0 + glob 2.1.1 + http_multi_server 3.2.1 + http_parser 4.0.2 + io 1.0.4 js 0.6.5 (0.6.7 available) + logging 1.1.1 matcher 0.12.13 (0.12.14 available) meta 1.8.0 (1.9.0 available) + mime 1.0.4 + node_preamble 2.0.1 + package_config 2.1.0 path 1.8.2 (1.8.3 available) + pool 1.5.1 + pub_semver 2.1.3 + shelf 1.4.0 + shelf_packages_handler 3.0.1 + shelf_static 1.1.1 + shelf_web_socket 1.0.3 + source_map_stack_trace 2.1.1 + source_maps 0.10.11 + 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) + watcher 1.0.2 + web_socket_channel 2.3.0 webdriver 3.0.1 (3.0.2 available) + webkit_inspection_protocol 1.2.0 + yaml 3.1.1 Changed 28 dependencies!
Untuk menangani navigasi aplikasi, tambahkan go_router:
$ flutter pub add go_router Resolving dependencies... archive 3.3.2 (3.3.6 available) collection 1.17.0 (1.17.1 available) + flutter_web_plugins 0.0.0 from sdk flutter + go_router 6.0.4 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) Changed 2 dependencies!
Dependensi berikut seharusnya sudah ditambahkan ke pubspec.yaml Anda:
Di bagian dependencies
:
dependencies: provider: ^6.0.5 go_router: ^6.0.4
Di bagian dev_dependencies
:
dev_dependencies: integration_test: sdk: flutter flutter_driver: sdk: flutter test: ^1.22.0
Buka project di editor kode pilihan Anda, lalu jalankan aplikasi. Atau, jalankan aplikasi di command line sebagai berikut.
$ flutter run
4. Membangun aplikasi
Berikutnya, Anda akan membangun aplikasi sehingga Anda dapat mengujinya. Aplikasi berisi file berikut:
lib/models/favorites.dart
- membuat class model untuk daftar favoritlib/screens/favorites.dart
- membuat tata letak untuk daftar favoritlib/screens/home.dart
- membuat daftar itemlib/main.dart
- file utama tempat aplikasi dimulai
Pertama, buat model Favorites
di lib/models/favorites.dart
Buat direktori baru bernama models
di direktori lib
, lalu buat file baru bernama favorites.dart
. Di file tersebut, tambahkan kode berikut:
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();
}
}
Tambahkan Halaman favorit di lib/screens/favorites.dart
Buat direktori baru bernama screens
di direktori lib
, lalu di direktori tersebut, buat file baru bernama favorites.dart
. Di file tersebut, tambahkan kode berikut:
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),
),
);
},
),
),
);
}
}
Tambahkan Halaman beranda di lib/screens/home.dart
Di direktori lib/screens
, buat file baru lainnya yang bernama home.dart
. Di lib/screens/home.dart
, tambahkan kode berikut:
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),
),
);
},
),
),
);
}
}
Ganti konten lib/main.dart
Ganti konten lib/main.dart
dengan kode berikut:
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(
primarySwatch: Colors.blue,
useMaterial3: true,
),
routerConfig: _router,
),
);
}
}
Aplikasi sudah selesai, tetapi belum diuji.
Jalankan aplikasi. Tampilannya akan terlihat seperti screenshot ini:
Aplikasi menampilkan daftar item. Ketuk ikon berbentuk hati di baris mana saja untuk mengisi hati dan menambahkan item ke daftar favorit. Tombol Favorit di AppBar
mengarahkan Anda ke layar kedua yang berisi daftar favorit.
Kini aplikasi sudah siap untuk pengujian. Anda akan mulai menguji aplikasi di langkah berikutnya.
5. Melakukan pengujian unit pada penyedia
Anda akan memulai dengan melakukan pengujian unit pada model favorites
. Apa itu pengujian unit? Pengujian unit memverifikasi bahwa setiap unit software, baik berupa fungsi, objek, ataupun widget, menjalankan tugasnya dengan benar.
Semua file pengujian di aplikasi Flutter, kecuali untuk pengujian integrasi, ditempatkan di direktori test
.
Hapus test/widget_test.dart
Sebelum memulai pengujian, hapus file widget_test.dart
. Anda akan menambahkan file pengujian Anda sendiri.
Membuat file pengujian baru
Pertama, Anda akan menguji metode add()
di model Favorites
untuk memastikan bahwa item baru ditambahkan ke daftar, dan daftar tersebut mencerminkan perubahan. Berdasarkan konvensi, struktur direktori di direktori test
meniru yang ada di direktori lib
dan file Dart memiliki nama yang sama, dengan tambahan _test
.
Buat direktori models
di direktori test
. Di direktori baru ini, buat file favorites_test.dart
dengan konten berikut:
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);
});
});
}
Framework pengujian Flutter memungkinkan Anda mengikat pengujian serupa yang terkait satu sama lain dalam grup. Mungkin terdapat beberapa grup dalam satu file pengujian yang ditujukan untuk menguji bagian yang berbeda dari file yang sesuai di direktori lib
.
Metode test()
menggunakan dua parameter posisi: description
pengujian dan callback
tempat sebenarnya Anda menulis pengujian tersebut.
Coba hapus item dari daftar. Masukkan pengujian berikut dalam grup Testing App Provider
yang sama:
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);
});
Menjalankan pengujian
Di command line, buka direktori utama project dan masukkan perintah berikut:
$ flutter test test/models/favorites_test.dart
Jika semuanya berfungsi, Anda akan melihat pesan seperti berikut:
00:06 +2: All tests passed!
File pengujian yang lengkap: test/models/favorites_test.dart
.
Untuk informasi selengkapnya terkait pengujian unit, kunjungi An introduction to unit testing.
6. Pengujian widget
Pada langkah ini, Anda akan menambahkan kode untuk menguji widget. Pengujian widget bersifat unik untuk Flutter, tempat Anda dapat menguji setiap widget secara terpisah. Langkah ini menguji layar HomePage
dan FavoritesPage
satu per satu.
Pengujian widget menggunakan fungsi testWidget()
, bukan fungsi test()
. Seperti fungsi test()
, fungsi testWidget()
menggunakan dua parameter: description,
dan callback
, tetapi callback-nya menggunakan WidgetTester
sebagai argumennya.
Pengujian widget menggunakan TestFlutterWidgetsBinding
, yaitu class yang menyediakan resource yang sama ke widget Anda seperti halnya di aplikasi yang berjalan, misalnya informasi tentang ukuran layar, kemampuan untuk menjadwalkan animasi, tetapi tanpa berjalan di dalam aplikasi. Sebagai gantinya, lingkungan virtual digunakan untuk membuat instance widget, lalu menjalankan pengujian hasil. Di sini, pumpWidget
memulai proses dengan memberi tahu framework untuk memasang dan mengukur widget tertentu seperti yang dilakukannya di aplikasi.
Framework pengujian widget memberikan pencari untuk menemukan widget, misalnya text()
, byType()
, dan byIcon().
. Framework ini juga memungkinkan pencocok memverifikasi hasil.
Mulai dengan menguji widget HomePage
.
Membuat file pengujian baru
Pengujian pertama memastikan apakah men-scroll HomePage
berfungsi dengan baik.
Buat file baru di direktori test
lalu beri nama home_test.dart
. Di file yang baru dibuat, tambahkan kode berikut:
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);
});
});
}
Fungsi createHomeScreen()
digunakan untuk membuat aplikasi yang memuat widget yang akan diuji di MaterialApp, yang digabungkan menjadi ChangeNotifierProvider. Widget HomePage memerlukan kedua widget ini berada di atasnya di hierarki widget agar dapat mewarisi dari kedua widget tersebut dan mendapatkan akses ke data yang ditawarkan. Fungsi ini diteruskan sebagai parameter ke fungsi pumpWidget()
.
Berikutnya, uji apakah framework dapat menemukan ListView
yang dirender ke layar.
Tambahkan cuplikan kode berikut ke 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);
});
});
Menjalankan pengujian
Pertama-tama, jalankan pengujian dengan cara yang sama seperti saat Anda menjalankan pengujian unit, menggunakan perintah:
$ flutter test test/home_test.dart
Pengujian akan berlangsung cepat, dan Anda akan melihat pesan seperti ini:
00:02 +2: All tests passed!
Anda juga dapat menjalankan pengujian widget menggunakan perangkat atau emulator, yang memungkinkan Anda melihat pengujian yang berjalan. Hal ini juga memberi Anda kemampuan untuk menggunakan hot restart.
Hubungkan perangkat ke sumber listrik atau mulai emulator Anda. Anda juga dapat menjalankan pengujian sebagai aplikasi desktop.
Dari command line, buka direktori utama project lalu masukkan perintah berikut:
$ flutter run test/home_test.dart
Anda mungkin perlu memilih perangkat tempat pengujian akan dijalankan. Dalam hal ini, ikuti petunjuk lalu pilih perangkatnya:
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"):
Jika semuanya berfungsi, Anda akan melihat output mirip seperti berikut:
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!
Berikutnya, Anda akan mengubah file pengujian lalu menekan Shift + R
untuk melakukan hot restart pada aplikasi dan menjalankan ulang semua pengujian. Jangan hentikan aplikasi.
Tambahkan pengujian lainnya ke grup yang menguji widget HomePage. Salin pengujian berikut ke file Anda:
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);
});
Pengujian ini memastikan bahwa mengetuk IconButton
akan mengubah Icons.favorite_border
(hati yang kosong) menjadi Icons.favorite
(hati yang terisi), kemudian kembali menjadi Icons.favorite_border
ketika diketuk lagi.
Tekan Shift + R
. Tindakan ini akan memulai hot restart pada aplikasi dan menjalan ulang semua pengujian.
File pengujian lengkap: test/home_test.dart
.
Gunakan proses yang sama untuk menguji FavoritesPage
dengan kode berikut. Ikuti langkah-langkah yang sama dan jalankan.
test/favorites_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/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);
});
});
}
Pengujian ini memastikan apakah item menghilang ketika tombol tutup (hapus) ditekan.
Untuk informasi selengkapnya mengenai pengujian widget, kunjungi:
7. Menguji UI aplikasi dengan pengujian integrasi
Pengujian integrasi digunakan untuk menguji cara setiap bagian aplikasi berfungsi sebagai satu kesatuan. Library integration_test
digunakan untuk melakukan pengujian integrasi di Flutter. Library ini adalah versi Flutter dari Selenium WebDriver, Protractor, Espresso, atau Earl Gray. Paket ini menggunakan flutter_driver
secara internal untuk menjalankan pengujian di perangkat.
Menjalankan pengujian integrasi di Flutter mirip dengan menulis pengujian widget, hanya saja pengujian ini dijalankan di perangkat seluler, browser, atau aplikasi desktop, yang disebut perangkat target.
Menulis pengujian
Buat direktori bernama integration_test
di direktori utama project, lalu buat file baru bernama app_test.dart
di direktori tersebut.
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);
}
});
});
}
Menjalankan pengujian
Hubungkan perangkat ke sumber listrik atau mulai emulator Anda. Anda juga dapat menjalankan pengujian sebagai aplikasi desktop.
Di command line, buka direktori utama project lalu masukkan perintah berikut:
$ flutter test integration_test/app_test.dart
Jika semuanya berfungsi, Anda akan melihat output mirip seperti ini:
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. Menguji performa aplikasi dengan Flutter Driver
Menulis pengujian performa
Buat file pengujian baru bernama perf_test.dart dalam folder integration_test dengan konten berikut:
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');
});
});
}
Fungsi ensureInitialized()
memastikan apakah driver pengujian integrasi telah diinisialisasi, dan akan melakukan inisialisasi ulang jika perlu. Menyetel framePolicy
sebagai fullyLive
adalah langkah yang bagus untuk menguji kode animasi.
Pengujian ini men-scroll daftar item dengan sangat cepat, kemudian men-scroll ke paling atas. Fungsi traceAction()
mencatat tindakan dan membuat ringkasan linimasa.
Mengambil hasil performa
Untuk mengambil hasil, buat folder bernama test_driver
dengan file bernama perf_driver.dart
, lalu tambahkan kode berikut:
test_driver/perf_driver.dart
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,
);
}
},
);
}
Menjalankan pengujian
Hubungkan perangkat ke sumber listrik atau mulai emulator Anda.
Di command line, buka direktori utama project lalu masukkan perintah berikut:
$ flutter drive \
--driver=test_driver/perf_driver.dart \
--target=integration_test/perf_test.dart \
--profile \
--no-dds
Jika semuanya berfungsi, Anda akan melihat output mirip seperti ini:
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.
Setelah pengujian berhasil, direktori build di root project akan berisi dua file:
scrolling_summary.timeline_summary.json
berisi ringkasan. Buka file dengan editor teks apa pun untuk meninjau informasi yang ada di dalamnya.scrolling_summary.timeline.json
berisi data linimasa lengkap.
Untuk detail selengkapnya terkait pengujian integrasi, buka:
9. Selamat!
Anda telah menyelesaikan codelab dan telah mempelajari berbagai cara untuk menguji aplikasi Flutter.
Yang telah Anda pelajari
- Cara menguji penyedia dengan bantuan pengujian unit
- Cara menguji widget menggunakan framework pengujian widget
- Cara menguji UI aplikasi menggunakan pengujian integrasi
- Cara menguji performa aplikasi menggunakan pengujian integrasi
Untuk mempelajari lebih lanjut pengujian di Flutter, buka