For the complete documentation index, see llms.txt. This page is also available as Markdown.

API Testing

API testing (atau integration testing) adalah pengujian untuk memastikan API yang dibangun sesuai dengan kontrak yang telah ditetapkan. Berbeda dengan unit testing yang menguji komponen secara terisolasi, API testing menggunakan server dan database sungguhan (bukan mock) untuk memverifikasi perilaku end-to-end.

πŸ“‚ Kode Lengkap Bab Ini: Seluruh kode yang dibahas di bab ini tersedia di GitHub:

πŸ”— github.com/jacky-htg/workshop/tree/main/21-apit-testing

21.1 Unit Testing vs API Testing vs E2E Testing

Aspek
Unit Testing
API Testing
E2E Testing

Fokus

Coverage & logika percabangan

Kontrak API & behavior

Flow satu journey (user story)

Database

Mock

Sungguhan (container)

Sungguhan (container)

Server

Tidak perlu

httptest

httptest

Cakupan

1 fungsi/method

1 endpoint

Multiple endpoint dalam satu skenario

Kecepatan

Sangat cepat

Cepat

Sedang

Biaya maintenance

Rendah

Sedang

Tinggi

21.2 Struktur Folder Testing

Kita akan mengelompokkan test berdasarkan jenisnya:

project/
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ handler/
β”‚   β”‚   β”œβ”€β”€ role.go
β”‚   β”‚   └── role_test.go           βœ… Unit test (package yang sama)
β”‚   β”œβ”€β”€ service/
β”‚   β”‚   β”œβ”€β”€ role.go
β”‚   β”‚   └── role_test.go           βœ… Unit test (package yang sama)
β”‚   └── repository/
β”‚       β”œβ”€β”€ role.go
β”‚       └── role_test.go           βœ… Unit test (package yang sama)
β”‚
└── test/                          βœ… API/E2E tests (folder terpisah)
    β”œβ”€β”€ api/
    β”‚   β”œβ”€β”€ auth/
    β”‚   β”‚   β”œβ”€β”€ main_test.go
    β”‚   β”‚   └── login_test.go
    β”‚   └── role/
    β”‚       β”œβ”€β”€ main_test.go
    β”‚       └── create_test.go
    └── e2e/
        β”œβ”€β”€ helper/
        β”‚   β”œβ”€β”€ base_helper.go
        β”‚   β”œβ”€β”€ auth_helper.go
        β”‚   β”œβ”€β”€ role_helper.go
        β”‚   β”œβ”€β”€ user_helper.go
        β”‚   └── access_helper.go
        └── rbac/
            β”œβ”€β”€ main_test.go
            └── rbac_test.go

21.3 Database Container dengan Testcontainers

API testing membutuhkan database sungguhan. Ada dua pendekatan:

Pendekatan
Kelebihan
Kekurangan

Database dedicated

Cepat, stabil

Race condition antar test, data bersinggungan

Database on-the-fly

Isolated, clean state

Lebih lambat (start container)

Pendekatan database on-the-fly membuat container database saat test dimulai dan menghapusnya setelah selesai. Hal ini bisa dilakukan dengan memanfaatkan perintah exec.Command yang bisa digunakan untuk menjalankan perintah docker run maupun docker container rm -f.

Pendekatan native exec.Command() mempunyai keunggulan di performance, namun untuk alasan kemudahan dalam maintenance, Kita akan menggunakan pendekatan on-the-fly dengan library testcontainers-go.

PostgreSQL Container

Container Registry (Singleton)

Untuk mengelola banyak container (PostgreSQL, Redis, dll), buat registry dengan pattern singleton:

21.4 Setup TestMain

TestMain adalah fungsi khusus di Go yang dijalankan sekali sebelum semua test dalam package dieksekusi. Kita gunakan untuk:

  1. Start container database

  2. Jalankan migration

  3. Scan access routes

  4. Start HTTP test server

  5. Cleanup setelah semua test selesai

Data Pendukung

Untuk data accesses routing, saya membuat data test test/data/router.go:

TestMain di Setiap Package Test

Setiap package test memiliki TestMain sendiri, misalnya di paket auth, buat file test/api/auth/main_test.go

21.5 Helper untuk API Call

Buat helper untuk memanggil API dengan mudah. Update file test/setup/setup.go untuk menambahkan helper ini :

21.6 Auth API Test

Login Scenarios

Buat file test/api/auth/login_test.go, pastikan seluruh skenario yang ada di api kontrak tercover dalam api testing.

21.7 Role API Test

Create Role Scenarios

Buat file test/api/role/create_test.go :

21.8 E2E Testing

Flow E2E Testing untuk RBAC :

  1. Login with non-existent user (negative test)

  2. Login as admin (prepare pembuatan user baru dari user yang tidak ada di langkah 1)

  3. Verify role does NOT exist (mengecek bahwa role baru yang hendak diinput belum ada di database)

  4. Create role (membuat role baru)

  5. Verify role by ID (memverifikasi role baru telah terbuat)

  6. Create user (Membuat user baru dari data user di langkah 1)

  7. Verify user by ID (memverifikasi pembuatan user baru berhasil)

  8. Login as new user (mendapatkan token dari user yang baru dibuat)

  9. Access /accesses without permission (should be forbidden, sesuai ekspektasi user baru belum punya permissions)

  10. Get permission IDs (mendapatkan AccessIDs dari ekspektasi list permission yang hendak di-grant ke role baru, persiapan sebelum memanggil langkah grant access)

  11. Grant access to role (memberi akses ke role yang telah dibuat)

  12. Access /accesses with permission (should succeed, GET /access seharusnya bisa diakses setelah role di-grant)

Prinsip FailNow

Berbeda dengan api testing yang melakukan asserting, e2e testing yang merajut multiple endpoin dalam satu flow membutuhkan prinsip FailNow yang jika pada suatu titik ada yang tidak sesuai dengan ekspektasi, maka proses pengujian akan dihentikan saat itu juga. Untuk itu, kita akan menggunakan perintah require (bukan assert) dalam membandingkan ekspektasi dengan aktual.

Pembuatan Base Helper

Auth Helper

Role Helper

User Helper

Access Helper

E2E Test : RBAC Flow

21.9 Build Tag

Tambahkan build tag //go:build integration di semua file API test. Ini memungkinkan kita menjalankan unit test dan API test secara terpisah.

Konfigurasi VS Code: Buat .vscode/settings.json agar build tag dikenali:

kemudian retart gopl. (mac -> shift+cmd+p, muncul promp, kli GO: Restart Language Server)

Menjalankan Test:

Ringkasan Bab 21

Di bab ini kita telah belajar:

Komponen
Lokasi
Fungsi

PostgreSQL Container

test/containers/postgres.go

Membuat database container on-the-fly

Container Registry

test/containers/registry.go

Singleton manager untuk semua container

Setup Test

test/setup/setup.go

Inisialisasi server, migrasi, scan access

API Helpers

test/setup/setup.go

CallAPI(), GetToken()

Auth Test

test/api/auth/

Test endpoint /login

Role Test

test/api/role/

Test CRUD roles

E2E Helpers

test/e2e/helper/

Helper untuk setiap resource

E2E Test

test/e2e/rbac/

End-to-end flow RBAC

Manfaat yang kita peroleh:

  • βœ… API teruji secara end-to-end dengan database sungguhan

  • βœ… Test terisolasi (container on-the-fly)

  • βœ… Build tag memisahkan unit test dan integration test

  • βœ… Helper yang reusable untuk berbagai skenario

Yang akan datang:

  • Saat ini kita belum membahas cache

  • Bab selanjutnya: Cache – meningkatkan performa dengan caching

Last updated