Belajar Flutter - Testing & Quality Assurance
Episode 13 of 23

Belajar Flutter - Testing & Quality Assurance

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.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

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 Testing Logika Dart

Struktur Test Dasar

Unit test menguji logika murni — model, repository, kalkulasi — tanpa UI. Semua test Flutter memakai package flutter_test:

Unit test sederhana
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.

Group dan Deskripsi

Untuk test yang banyak, gunakan group agar output terorganisasi:

Test dengan group
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:

Menjalankan seluruh test
flutter test

flutter test menjalankan semua file _test.dart di folder test/. Setiap perubahan pada logika bisnis harus disertai test yang memperbaruinya.

Widget Testing dan Golden Tests

Widget Test: Menguji UI dalam Isolasi

Widget test menjalankan UI di lingkungan simulasi tanpa device:

Widget test sederhana
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 Tests

Golden test membandingkan render widget dengan gambar referensi (snapshot):

Golden test sederhana
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 Testing

integration_test untuk Alur Penuh

Integration test menjalankan aplikasi di device atau emulator dan menguji alur end-to-end:

Menambahkan integration_test
dev_dependencies:
  flutter_test:
    sdk: flutter
  integration_test:
    sdk: flutter

Tambahkan integration_test dari SDK ke dev_dependencies. Test ditulis di folder integration_test/:

Integration test alur login
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.

flutter drive untuk Eksekusi di Device

Jalankan integration test di device:

Menjalankan integration test
flutter test integration_test -d linux

flutter test integration_test -d linux menjalankan seluruh folder integration test di device yang ditentukan. Target -d bisa emulator, physical device, atau desktop.

Continuous Testing dan Test Automation

Test di Setiap Commit

Jalankan rangkaian test di CI sebelum merge:

Lint dan test dalam satu perintah
flutter analyze && flutter test

flutter 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.

Ukuran Coverage

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.

Penutup

Inti yang harus dibawa pulang:

  • Unit test menguji logika murni dengan test dan expect.
  • flutter test menjalankan seluruh rangkaian di folder test/.
  • Widget test mensimulasikan tap dan verifikasi tampilan tanpa device.
  • Golden test membandingkan tampilan dengan snapshot referensi.
  • Integration test menjalankan aplikasi sungguhan dengan flutter_test dan integration_test.
  • Otomatisasi dengan 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.

Belajar Flutter - Testing & Quality Assurance | Belajar Flutter