Belajar Dart - Testing & Quality
Episode 9 of 23

Belajar Dart - Testing & Quality

Episode ini membahas pengujian Dart: menulis unit test dengan package:test, grouping dan setup-teardown, penggunaan matcher, mocking dependency, integration test, serta menjalankan semua test dengan dart test.

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

Pendahuluan

Kode tanpa tes adalah bom waktu. Episode 9 membawa kalian ke praktik testing dan quality di Dart: menulis unit test dengan package:test, mengelompokkan test, memanfaatkan setup dan teardown, memakai matcher untuk asersi yang ekspresif, serta menguji kode yang bergantung pada layanan eksternal lewat mocking.

Pengujian bukan sekadar tugas tambahan — ia adalah umpan balik tercepat yang memastikan kalian bisa mengubah kode dengan percaya diri. Semakin cepat test berjalan, semakin sering kalian akan menjalankannya.

Di akhir episode ini, project kalian akan memiliki fondasi test yang bisa tumbuh bersama kode.

Struktur Test Dasar

Pastikan test ada di dev_dependencies, lalu tulis file test di direktori test/:

Unit test pertama
import 'package:test/test.dart';
 
int tambah(int a, int b) => a + b;
 
void main() {
  test('tambah dua angka', () {
    expect(tambah(2, 3), 5);
  });
}

Fungsi test('deskripsi', () {...}) mendefinisikan satu kasus pengujian, dan expect(nilai, matcher) memverifikasi hasil. Jalankan dengan:

Menjalankan semua test
dart test

dart test menemukan dan menjalankan semua file di direktori test/, lalu menampilkan ringkasan lulus dan gagal.

Asersi dengan Matcher

Matcher membuat asersi lebih ekspresif daripada sekadar membandingkan nilai:

Beragam matcher
import 'package:test/test.dart';
 
void main() {
  test('beragam asersi', () {
    expect([1, 2, 3], contains(2));
    expect('halo', startsWith('ha'));
    expect(() => throw Exception('x'), throwsException);
  });
}

contains(2) memeriksa keanggotaan dalam koleksi, startsWith('ha') memeriksa awalan string, dan throwsException memastikan fungsi melempar error. Matcher bersifat komposable sehingga asersi kompleks tetap terbaca.

Grouping, Setup, dan Teardown

Group untuk Organisasi

Kelompokkan test yang berkaitan dengan group agar laporan hasil lebih terstruktur:

Grouping test
import 'package:test/test.dart';
 
void main() {
  group('Kalkulator', () {
    test('tambah', () {
      expect(1 + 1, 2);
    });
 
    test('kurang', () {
      expect(5 - 2, 3);
    });
  });
}

group('Kalkulator', ...) membungkus test bertema sama. Saat ada kegagalan, laporan menunjukkan grup dan nama test yang spesifik.

setUp dan tearDown

Gunakan setUp untuk menyiapkan state bersama dan tearDown untuk membersihkannya:

Setup dan teardown
import 'package:test/test.dart';
 
late List<String> penyimpanan;
 
void main() {
  setUp(() {
    penyimpanan = [];
  });
 
  test('menyimpan data', () {
    penyimpanan.add('item');
    expect(penyimpanan.length, 1);
  });
}

setUp(() {...}) dijalankan sebelum setiap test, sehingga setiap test dimulai dengan state yang bersih. tearDown berguna untuk menutup koneksi atau menghapus file sementara.

Mocking Dependency dan Integration Test

Mem-mock Layanan Eksternal

Saat unit tidak boleh menyentuh jaringan atau database, mock dependency-nya. Gunakan package:mockito yang digabung dengan build_runner:

Mock dengan mockito
import 'package:mockito/mockito.dart';
 
class KlienApi {
  Future<String> ambilData() async => 'nyata';
}
 
class MockKlienApi extends Mock implements KlienApi {}
 
void main() {
  test('mock mengembalikan data palsu', () async {
    var klien = MockKlienApi();
    when(klien.ambilData()).thenAnswer((_) async => 'palsu');
    expect(await klien.ambilData(), 'palsu');
  });
}

when(klien.ambilData()).thenAnswer(...) memprogram perilaku mock tanpa menjalankan implementasi asli. Ini membuat test cepat dan deterministik.

Integration Test

Integration test memverifikasi kerja sama antar komponen nyata — misalnya HTTP server lokal yang benar-benar berjalan:

Menjalankan integration test
dart test test/integration/

dart test test/integration/ menjalankan hanya test di subdirektori integration. Bedakan unit test yang cepat dengan integration test yang lambat agar suite tetap ringan.

Mengukur Kualitas dengan Coverage

Coverage memberi gambaran seberapa banyak kode yang dieksekusi oleh test:

Mengukur coverage
dart test --coverage=coverage
dart pub global activate coverage
format_coverage --lcov --in=coverage --out=coverage/lcov.info

Setelah dart test --coverage=coverage, tool format_coverage mengubah hasil menjadi format lcov yang bisa dibaca alat seperti coveralls. Bidik coverage tinggi pada logika bisnis, bukan sekadar mengejar persentase global.

Penutup

Inti yang harus dibawa pulang:

  • test() dan expect() adalah fondasi unit test dengan package:test.
  • Matcher seperti contains, startsWith, dan throwsException membuat asersi ekspresif.
  • group mengorganisasi test; setUp dan tearDown menjaga state tetap bersih.
  • Mock dengan mockito menggantikan dependency eksternal agar test cepat.
  • Integration test di subdirektori sendiri agar suite tetap ringan.
  • dart test --coverage=coverage mengukur seberapa banyak kode yang teruji.

Di episode 10 selanjutnya kita akan membahas server-side Dart dan backend — membangun HTTP server dengan Shelf, routing dan middleware, serialisasi JSON serta persistence, dan deployment aplikasi server Dart ke produksi.

Belajar Dart - Testing & Quality | Belajar Dart