Pengantar Unit Testing: Coding Tanpa Khawatir
Apa Itu Unit Testing?
Unit testing adalah salah satu jenis pengujian perangkat lunak yang berfokus pada pengujian unit-unit terkecil dalam sebuah sistem. Biasanya, ini mencakup pengujian function, method, dan class.
Unit testing adalah pengujian paling awal yang dilakukan oleh developer sebelum melakukan pengujian lain, seperti integration test atau end-to-end test. Tujuannya adalah menguji komponen tanpa bergantung pada sistem lain dan hanya menguji *function by function*.
Dalam piramida pengujian, Unit Testing berada di paling dasar, yang berarti paling cepat dan murah untuk dijalankan.
Analogi Unit Testing
Bayangkan saat mengecek setiap komponen mobil (seperti baut, ban, mesin) secara terpisah sebelum dirakit menjadi satu mobil utuh. Jika setiap komponen lulus tes, kita bisa yakin mobil rakitan pasti berkualitas. Jika ada masalah, kita tahu itu bukan dari komponen dasar.
Kenapa Unit Testing Itu Penting?
Unit testing membantu memastikan keandalan, kualitas, dan kemudahan pemeliharaan kode yang kita tulis. Manfaat utamanya adalah:
- Mendeteksi Bug Lebih Awal: Menemukan masalah di level fungsi sebelum digabung ke kode utama.
- Memberikan Dokumentasi Kode yang "Hidup": Test case berfungsi sebagai contoh cara menggunakan sebuah fungsi.
- Mempermudah Perubahan dan Refactoring: Memungkinkan developer mengubah kode (refactor) dengan percaya diri, karena jika ada yang rusak, unit test akan gagal dan memberitahu kita.
- Meningkatkan Kualitas Kode: Mendorong penulisan kode yang lebih modular dan rapi.
- Menghemat Waktu dan Biaya: Bug yang ditemukan di tahap awal jauh lebih murah dan cepat diperbaiki.
- Meningkatkan Kepercayaan Diri: Developer lebih percaya diri saat merilis kode baru.
Framework Populer
Ada banyak framework untuk melakukan unit testing, berikut tiga yang paling populer di ekosistemnya masing-masing:
- JUNIT 5 (Java): Framework de facto untuk Java. Digunakan jika kita bekerja dengan Java atau bahasa berbasis JVM lainnya (Kotlin, Scala).
- JEST (JavaScript): Framework buatan Meta yang efisien. Digunakan untuk React, Node.js, TypeScript, atau framework frontend modern lainnya.
- PYTEST (Python): Sederhana, mudah dibaca, dan kuat. Digunakan untuk proyek Python apapun, dari skrip sederhana hingga data science dan API.
Pola Dasar: Arrange, Act, Assert (AAA)
Pola AAA adalah pendekatan populer dalam penulisan unit test yang membagi setiap tes menjadi tiga bagian utama:
- Arrange (Menyiapkan): Menyiapkan kondisi awal tes. Ini termasuk membuat objek atau data yang diperlukan.
- Act (Melakukan): Menjalankan fungsi atau metode yang akan diuji.
- Assert (Memverifikasi): Memverifikasi bahwa hasil dari tindakan (Act) sesuai dengan ekspektasi.
Contoh Kode Unit Testing
Berikut adalah contoh penerapan unit testing menggunakan Pytest dan JUnit 5.
Contoh 1: Pytest (Python)
Kita memiliki kode untuk keranjang belanja (`ShoppingCart`) dan kita ingin mengujinya.
# Kode File: shopping_cart.py
# (Transkripsi dari PDF)
from typing import List
class ShoppingCart:
def __init__(self, max_size: int) -> None:
self.items: List[str] = []
self.max_size = max_size
def add(self, item: str):
if len(self.items) == self.max_size:
raise OverflowError("cannot add more items")
self.items.append(item)
def get_items(self) -> List[str]:
return self.items
def delete(self, item: str):
if item not in self.items:
raise ValueError("item not found")
self.items.remove(item)
# Kode File Test: test_shopping_cart.py
# (Transkripsi dari PDF)
import pytest
from shopping_cart import ShoppingCart
@pytest.fixture
def cart():
# ARRANGE (Fixture adalah bagian dari Arrange)
return ShoppingCart(5)
def test_add(cart):
# ACT
cart.add("apple")
# ASSERT
assert "apple" in cart.get_items()
assert len(cart.get_items()) == 1
def test_add_overflow(cart):
# ARRANGE (mengisi keranjang)
for i in range(5):
cart.add("item")
# ACT & ASSERT (menguji error)
with pytest.raises(OverflowError):
cart.add("item_terakhir")
def test_delete_item(cart):
# ARRANGE
cart.add("apple")
cart.add("banana")
# ACT
cart.delete("apple")
# ASSERT
assert "apple" not in cart.get_items()
assert cart.get_items() == ["banana"]
def test_delete_item_not_found(cart):
# ACT & ASSERT
with pytest.raises(ValueError):
cart.delete("grape")
Contoh 2: JUnit 5 (Java)
Kita memiliki kode sederhana untuk Akun Bank (`BankAccount`).
// Kode File: BankAccount.java
// (Transkripsi dari PDF)
package com.example;
public class BankAccount {
private int balance = 0;
public void deposit(int amount) {
balance += amount;
}
public void withdraw(int amount) {
if (amount > balance) {
throw new IllegalArgumentException("Saldo tidak cukup!");
}
balance -= amount;
}
public int getBalance() {
return balance;
}
}
// Kode File Test: BankAccountTest.java
// (Transkripsi dari PDF)
package com.example;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class BankAccountTest {
@Test
void testDeposit() {
// ARRANGE
BankAccount account = new BankAccount();
// ACT
account.deposit(100);
// ASSERT
assertEquals(100, account.getBalance());
}
@Test
void testWithdrawSuccess() {
// ARRANGE
BankAccount account = new BankAccount();
account.deposit(200);
// ACT
account.withdraw(50);
// ASSERT
assertEquals(150, account.getBalance());
}
@Test
void testWithdrawInsufficientFunds() {
// ARRANGE
BankAccount account = new BankAccount();
account.deposit(50);
// ACT & ASSERT
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
account.withdraw(100);
});
assertEquals("Saldo tidak cukup!", exception.getMessage());
}
}
← Kembali ke Daftar Blog