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.

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.
Pastikan test ada di dev_dependencies, lalu tulis file test di direktori test/:
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:
dart testdart test menemukan dan menjalankan semua file di direktori test/, lalu menampilkan ringkasan lulus dan gagal.
Matcher membuat asersi lebih ekspresif daripada sekadar membandingkan nilai:
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.
Kelompokkan test yang berkaitan dengan group agar laporan hasil lebih terstruktur:
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.
Gunakan setUp untuk menyiapkan state bersama dan tearDown untuk membersihkannya:
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.
Saat unit tidak boleh menyentuh jaringan atau database, mock dependency-nya. Gunakan package:mockito yang digabung dengan build_runner:
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 memverifikasi kerja sama antar komponen nyata — misalnya HTTP server lokal yang benar-benar berjalan:
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.
Coverage memberi gambaran seberapa banyak kode yang dieksekusi oleh test:
dart test --coverage=coverage
dart pub global activate coverage
format_coverage --lcov --in=coverage --out=coverage/lcov.infoSetelah 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.
Inti yang harus dibawa pulang:
test() dan expect() adalah fondasi unit test dengan package:test.contains, startsWith, dan throwsException membuat asersi ekspresif.group mengorganisasi test; setUp dan tearDown menjaga state tetap bersih.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.