Episode ini membangun kepercayaan diri terhadap kode: unit testing logika Dart dengan flutter_test, widget testing dan golden tests, integration testing dengan flutter_test dan flutter drive, serta continuous testing dan test automation untuk menjaga kualitas di setiap perubahan.

Aplikasi yang tumbuh tanpa tes adalah bom waktu: satu perubahan kecil bisa memecah fitur yang tidak terduga. Episode 13 membangun lapisan keamanan lewat pengujian terstruktur — dari unit test terkecil sampai integration test yang menjalankan aplikasi sungguhan.
Kita membahas unit testing logika Dart, widget testing dan golden tests, integration testing dengan flutter_test dan flutter drive, serta strategi continuous testing dan test automation.
Unit test menguji logika murni — model, repository, kalkulasi — tanpa UI. Semua test Flutter memakai package flutter_test:
import 'package:flutter_test/flutter_test.dart';
int tambah(int a, int b) => a + b;
void main() {
test('menjumlahkan dua angka', () {
expect(tambah(2, 3), 5);
});
}test mendefinisikan kasus uji dan expect memverifikasi hasil. Struktur ini adalah fondasi seluruh rangkaian pengujian — semuanya memakai pola test dan expect.
Untuk test yang banyak, gunakan group agar output terorganisasi:
group('Calculator', () {
test('mengembalikan 5 untuk 2 + 3', () {
expect(tambah(2, 3), 5);
});
test('mengembalikan 0 untuk angka negatif seimbang', () {
expect(tambah(-1, 1), 0);
});
});group membungkus beberapa test dalam satu kategori. Jalankan semua test dengan:
flutter testflutter test menjalankan semua file _test.dart di folder test/. Setiap perubahan pada logika bisnis harus disertai test yang memperbaruinya.
Widget test menjalankan UI di lingkungan simulasi tanpa device:
testWidgets('menampilkan nilai awal', (tester) async {
await tester.pumpWidget(const MaterialApp(home: CounterScreen()));
expect(find.text('Nilai: 0'), findsOneWidget);
await tester.tap(find.byType(FloatingActionButton));
await tester.pump();
expect(find.text('Nilai: 1'), findsOneWidget);
});tester.pumpWidget me-mount widget, tester.tap mensimulasikan ketukan, dan tester.pump() memproses rebuild. findsOneWidget memverifikasi keberadaan widget yang dicari.
Golden test membandingkan render widget dengan gambar referensi (snapshot):
testWidgets('sesuai golden', (tester) async {
await tester.pumpWidget(const MaterialApp(home: HomeScreen()));
await expectLater(
find.byType(HomeScreen),
matchesGoldenFile('goldens/home.png'),
);
});matchesGoldenFile('goldens/home.png') membandingkan tampilan dengan file referensi. Ketika desain berubah secara sah, perbarui golden dengan menjalankan test dengan flag --update-goldens. Golden test memastikan perubahan kecil yang tak terlihat sekalipun tidak luput.
Integration test menjalankan aplikasi di device atau emulator dan menguji alur end-to-end:
dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutterTambahkan integration_test dari SDK ke dev_dependencies. Test ditulis di folder integration_test/:
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('login berhasil', (tester) async {
app.main();
await tester.pumpAndSettle();
await tester.enterText(find.byKey(const Key('email')), 'user@example.com');
await tester.tap(find.byKey(const Key('login_button')));
await tester.pumpAndSettle();
expect(find.text('Selamat datang'), findsOneWidget);
});app.main() menjalankan aplikasi sungguhan, dan pumpAndSettle() menunggu semua animasi selesai. find.byKey memakai Key yang didefinisikan di widget — alasan penting memberi Key pada elemen interaktif penting.
Jalankan integration test di device:
flutter test integration_test -d linuxflutter test integration_test -d linux menjalankan seluruh folder integration test di device yang ditentukan. Target -d bisa emulator, physical device, atau desktop.
Jalankan rangkaian test di CI sebelum merge:
flutter analyze && flutter testflutter analyze && flutter test menggabungkan static analysis dan seluruh test. Pola ini wajib ada di pipeline CI — di seri ini, alur release di episode 14 dan runbook di episode 19 akan memakai fondasi yang sama.
flutter test --coverage menghasilkan laporan coverage. Target realistis bukan 100 persen mutlak, melainkan menutup logika kritikal: validasi, auth, dan pembayaran. Prioritaskan test yang menangkap regresi berbiaya tinggi.
Inti yang harus dibawa pulang:
test dan expect.flutter test menjalankan seluruh rangkaian di folder test/.flutter_test dan integration_test.flutter analyze && flutter test di CI.Di episode 14 selanjutnya kita membahas deployment dan release management — membangun release app bundle untuk Android dan iOS, code signing, provisioning profiles, dan app store submission, deployment web dan packaging desktop, serta release channels dan versioning. Aplikasi kalian siap dikirim ke pengguna.