DEV Community

Cover image for Asersi API: Panduan Praktis Memvalidasi Respons
Walse
Walse

Posted on • Originally published at apidog.com

Asersi API: Panduan Praktis Memvalidasi Respons

Permintaan API yang mengembalikan respons belum tentu berarti pengujian berhasil. Itu hanya berarti server menjawab. Pengujian baru bernilai ketika ada assertion yang memeriksa bahwa respons tersebut benar: status sesuai, body valid, schema cocok, header tepat, dan error ditangani dengan format yang diharapkan.

Coba Apidog hari ini

Panduan ini membahas cara menulis assertion API yang praktis: apa yang perlu diperiksa, kesalahan umum yang harus dihindari, dan bagaimana membangun assertion secara visual di Apidog tanpa harus menulis banyak skrip.

Apa itu assertion API

Assertion adalah pernyataan yang harus benar agar sebuah test dianggap berhasil.

Alurnya sederhana:

  1. Kirim request ke API.
  2. API mengembalikan response.
  3. Assertion membandingkan response aktual dengan kondisi yang diharapkan.
  4. Jika cocok, test lulus. Jika tidak, test gagal.

Contoh assertion sederhana:

Status response harus 200
Field $.email harus ada
Field $.id harus sama dengan id yang diminta
Response time harus di bawah 600 ms
Enter fullscreen mode Exit fullscreen mode

Tanpa assertion, automated test hanya membuktikan bahwa endpoint bisa dijangkau. Dengan assertion, test membuktikan bahwa endpoint mengembalikan data yang benar.

Inilah perbedaannya:

Buruk:
GET /users/123 -> response diterima

Lebih baik:
GET /users/123
- status = 200
- $.id = 123
- $.email ada
- schema sesuai User
- response time < 600 ms
Enter fullscreen mode Exit fullscreen mode

Assertion yang baik harus:

  • Spesifik: satu assertion memeriksa satu hal.
  • Stabil: tidak bergantung pada data volatile seperti timestamp presisi atau UUID acak.
  • Mudah dibaca: ketika gagal, penyebabnya langsung terlihat.
  • Independen jika memungkinkan: kegagalan satu assertion tidak membuat error lain menjadi membingungkan.

Assertion kode status, dan mengapa itu belum cukup

Assertion paling dasar adalah memeriksa HTTP status code.

Contoh:

GET /users/123 -> 200
POST /users -> 201
POST /users dengan payload invalid -> 400
GET /profile tanpa token -> 401
Enter fullscreen mode Exit fullscreen mode

Ini wajib, tetapi tidak cukup.

Jika API mengembalikan 200 OK, body-nya tetap bisa salah:

{
  "error": "database_timeout"
}
Enter fullscreen mode Exit fullscreen mode

Atau:

{
  "id": null,
  "email": null
}
Enter fullscreen mode Exit fullscreen mode

Status code hanya memberi tahu bahwa request diproses. Status code tidak menjamin data di dalam body benar.

Jika API Anda belum konsisten dalam penggunaan status code, baca juga kode status HTTP apa yang harus digunakan API REST.

Gunakan status code sebagai assertion pertama, bukan satu-satunya assertion.

Jenis assertion yang perlu ditulis

1. Assertion body response

Gunakan assertion body untuk memeriksa nilai aktual di response.

Contoh untuk endpoint login:

{
  "token": "abc.def.ghi",
  "expires_in": 3600
}
Enter fullscreen mode Exit fullscreen mode

Assertion yang layak:

$.token ada
$.token adalah string tidak kosong
$.expires_in = 3600
Enter fullscreen mode Exit fullscreen mode

Contoh untuk endpoint order:

$.total sama dengan jumlah item line
$.currency = "IDR"
$.status = "paid"
Enter fullscreen mode Exit fullscreen mode

Assertion ini menangkap bug logika yang tidak terlihat dari status code.

2. Assertion schema

Schema assertion memvalidasi bentuk response.

Contoh schema sederhana untuk user:

{
  "type": "object",
  "required": ["id", "email", "role"],
  "properties": {
    "id": { "type": "string" },
    "email": { "type": "string" },
    "role": {
      "type": "string",
      "enum": ["admin", "member", "viewer"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Assertion schema membantu mendeteksi contract drift, misalnya backend mengubah:

"email": "user@example.com"
Enter fullscreen mode Exit fullscreen mode

menjadi:

"email": {
  "value": "user@example.com"
}
Enter fullscreen mode Exit fullscreen mode

Perubahan seperti ini bisa merusak client walaupun status response tetap 200.

Topik ini berkaitan erat dengan pengujian kontrak API.

3. Assertion header

Header juga bagian dari kontrak API.

Contoh assertion header:

Content-Type berisi application/json
Cache-Control sesuai aturan caching
Access-Control-Allow-Origin tersedia jika endpoint digunakan browser
Strict-Transport-Security tersedia untuk endpoint HTTPS
Enter fullscreen mode Exit fullscreen mode

Untuk API publik atau API yang digunakan frontend, header sering sama pentingnya dengan body.

4. Assertion response time

Tambahkan budget latensi.

Contoh:

Response time < 800 ms
Enter fullscreen mode Exit fullscreen mode

Ini bukan pengganti load testing, tetapi cukup berguna untuk menangkap regresi performa dasar dalam functional test.

Contoh kasus:

Sebelumnya: GET /products selesai dalam 250 ms
Setelah perubahan query: GET /products menjadi 1800 ms
Enter fullscreen mode Exit fullscreen mode

Assertion response time akan membuat regresi seperti ini terlihat lebih awal.

5. Assertion error response

Negative test juga harus punya assertion body, bukan hanya status code.

Contoh request invalid:

POST /users
Content-Type: application/json

{
  "email": "not-an-email"
}
Enter fullscreen mode Exit fullscreen mode

Response yang diharapkan:

{
  "error": "validation_error",
  "details": [
    {
      "field": "email",
      "message": "Invalid email format"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Assertion:

status = 400
$.error = validation_error
$.details[0].field = email
response tidak mengandung stack trace
response tidak membocorkan data sensitif
Enter fullscreen mode Exit fullscreen mode

Negative test tanpa assertion body hanya membuktikan bahwa API menolak request. Assertion body membuktikan bahwa API menolaknya dengan benar.

6. Assertion keamanan

Untuk endpoint yang membutuhkan autentikasi dan otorisasi, tambahkan assertion keamanan.

Contoh:

Request tanpa token -> 401
Request dengan token expired -> 401
User A mengakses resource User B -> 403
Response tidak mengembalikan data sensitif
Payload injeksi tidak dipantulkan tanpa escaping
Enter fullscreen mode Exit fullscreen mode

Assertion keamanan sebaiknya menjadi bagian dari regression test, bukan hanya dicek manual.

Kesalahan umum saat menulis assertion

Terlalu spesifik pada data volatile

Hindari assertion seperti ini:

$.created_at = "2025-01-01T10:15:30.123Z"
$.id = "generated-random-uuid"
Enter fullscreen mode Exit fullscreen mode

Lebih stabil:

$.created_at ada
$.created_at valid sebagai datetime
$.id ada
$.id adalah string tidak kosong
Enter fullscreen mode Exit fullscreen mode

Assert nilai pasti hanya untuk data yang memang stabil.

Happy path hanya memeriksa status code

Happy path adalah jalur yang paling sering digunakan user. Justru di sinilah assertion harus lebih lengkap.

Buruk:

POST /auth/login -> status 200
Enter fullscreen mode Exit fullscreen mode

Lebih baik:

POST /auth/login
- status = 200
- $.token ada
- $.token adalah string
- $.expires_in = 3600
- schema sesuai LoginResponse
- response time < 800 ms
Enter fullscreen mode Exit fullscreen mode

Assertion bergantung pada urutan secara tersembunyi

Jika assertion B hanya valid setelah assertion A berhasil, buat dependensinya eksplisit dalam skenario test.

Contoh:

1. POST /users
   - status = 201
   - $.id ada
   - simpan $.id sebagai user_id

2. GET /users/{{user_id}}
   - status = 200
   - $.id = {{user_id}}
Enter fullscreen mode Exit fullscreen mode

Jangan membuat test kedua diam-diam bergantung pada nilai yang mungkin tidak pernah dibuat.

Satu assertion melakukan terlalu banyak hal

Hindari assertion abstrak seperti:

response benar
Enter fullscreen mode Exit fullscreen mode

Pisahkan menjadi beberapa assertion konkret:

status = 200
$.token ada
$.expires_in = 3600
Content-Type berisi application/json
Enter fullscreen mode Exit fullscreen mode

Setiap assertion yang gagal harus memberi sinyal jelas.

Mengabaikan negative case

Banyak tim menulis assertion lengkap untuk success case, tetapi hanya memeriksa 400 atau 401 untuk failure case.

Tambahkan assertion error:

status = 400
$.error = validation_error
$.details berisi field yang invalid
response tidak berisi password, token, atau stack trace
Enter fullscreen mode Exit fullscreen mode

Membangun assertion di Apidog

Di Apidog, assertion dapat dibuat lewat test builder visual. Anda tidak harus menulis skrip untuk sebagian besar pemeriksaan umum.

Untuk setiap request dalam test scenario, buka panel assertion dan tambahkan pemeriksaan berikut.

1. Tambahkan assertion status

Contoh:

Response status equals 200
Enter fullscreen mode Exit fullscreen mode

Gunakan ini untuk memastikan endpoint mengembalikan status yang sesuai.

2. Tambahkan assertion body dengan JSONPath

Contoh untuk login response:

{
  "token": "abc.def.ghi",
  "expires_in": 3600
}
Enter fullscreen mode Exit fullscreen mode

Assertion:

$.token exists
$.token is not empty
$.expires_in equals 3600
Enter fullscreen mode Exit fullscreen mode

Apidog membaca struktur response, sehingga Anda bisa memilih field dari response daripada mengetik path secara manual dari nol.

3. Tambahkan assertion schema

Validasi response terhadap schema endpoint.

Jika desain API dan test berada di workspace yang sama, schema yang digunakan assertion selaras dengan dokumentasi API. Ini mengurangi risiko schema test berbeda dari schema dokumentasi.

4. Tambahkan assertion response time

Contoh:

Response time less than 800 ms
Enter fullscreen mode Exit fullscreen mode

Gunakan angka yang realistis untuk environment test Anda. Jangan menyamakan budget lokal, staging, dan production jika infrastrukturnya berbeda.

5. Gunakan script custom hanya jika perlu

Sebagian besar assertion dapat dibuat secara visual:

status
header
body field
schema
response time
Enter fullscreen mode Exit fullscreen mode

Gunakan JavaScript post-processor hanya untuk logika yang lebih kompleks, misalnya:

membandingkan nilai antar-request
menghitung nilai turunan
conditional assertion berdasarkan response sebelumnya
Enter fullscreen mode Exit fullscreen mode

Untuk cakupan yang lebih luas, jalankan assertion yang sama dengan data berbeda menggunakan masukan pengujian berbasis data.

Saat scenario berjalan, laporan yang dihasilkan menunjukkan assertion mana yang gagal, request mana yang bermasalah, serta nilai expected dan actual.

Scenario yang sama juga dapat dijalankan di CI. Lihat panduan mengotomatiskan pengujian API di CI/CD untuk wiring pipeline. Anda juga bisa Unduh Apidog dan mulai membuat assertion untuk endpoint sendiri.

Contoh assertion untuk GET /users/{id}

Misalnya endpoint berikut mengembalikan objek user:

GET /users/123
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "id": "123",
  "email": "user@example.com",
  "role": "member",
  "created_at": "2025-01-01T10:15:30Z"
}
Enter fullscreen mode Exit fullscreen mode

Assertion untuk happy path:

status = 200
Content-Type berisi application/json
$.id = 123
$.email ada
$.email cocok dengan pola email
$.role salah satu dari admin, member, viewer
$.created_at ada
body sesuai schema User
response time < 600 ms
Enter fullscreen mode Exit fullscreen mode

Contoh schema User:

{
  "type": "object",
  "required": ["id", "email", "role", "created_at"],
  "properties": {
    "id": { "type": "string" },
    "email": { "type": "string" },
    "role": {
      "type": "string",
      "enum": ["admin", "member", "viewer"]
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Untuk unknown user:

GET /users/unknown-id
Enter fullscreen mode Exit fullscreen mode

Assertion:

status = 404
$.error = not_found
body tidak mengandung email
body tidak mengandung role
body tidak mengandung data user lain
Enter fullscreen mode Exit fullscreen mode

Dengan dua request ini, Anda sudah memverifikasi:

status
body
schema
header
response time
error behavior
Enter fullscreen mode Exit fullscreen mode

Itulah perbedaan antara test suite yang benar-benar melindungi rilis dan test suite yang hanya melakukan ping ke server.

Assertion dalam pipeline CI

Assertion paling berguna ketika dijalankan otomatis.

Jika test hanya dijalankan manual seminggu sekali, bug bisa terlambat ditemukan. Jika test dijalankan di CI pada setiap pull request, bug bisa ditemukan sebelum merge.

Di pipeline CI, ada dua hal penting.

1. Failure message harus jelas

Kurang berguna:

API test failed
Enter fullscreen mode Exit fullscreen mode

Lebih berguna:

POST /auth/login failed
Expected $.expires_in = 3600
Actual $.expires_in = 7200
Enter fullscreen mode Exit fullscreen mode

Assertion yang spesifik membuat developer tahu harus mulai debug dari mana.

2. Assertion harus stabil lintas environment

Hindari hard-code data production di test staging.

Buruk:

$.id = "prod-user-123"
Enter fullscreen mode Exit fullscreen mode

Lebih stabil:

$.id exists
$.id is string
Enter fullscreen mode Exit fullscreen mode

Atau gunakan environment variable:

$.id = {{test_user_id}}
Enter fullscreen mode Exit fullscreen mode

Pola praktis:

Baseline assertion:
- status
- schema
- header utama
- response time dasar

Environment-specific assertion:
- id user tertentu
- role tertentu
- data seed tertentu
Enter fullscreen mode Exit fullscreen mode

Jalankan baseline di semua environment. Tambahkan assertion nilai spesifik hanya di environment yang datanya stabil.

FAQ

Apa perbedaan assertion dan test case?

Test case adalah skenario lengkap: request, input, kondisi, dan expected result. Assertion adalah pemeriksaan individual di dalam test case yang menentukan lulus atau gagal.

Contoh:

Test case:
Login dengan email dan password valid

Assertion:
- status = 200
- $.token ada
- $.expires_in = 3600
Enter fullscreen mode Exit fullscreen mode

Baca juga cara menulis kasus pengujian API.

Berapa banyak assertion yang ideal untuk satu request?

Untuk sebagian besar endpoint, empat sampai delapan assertion sudah cukup:

status
header penting
field body utama
schema
response time
error shape jika negative case
Enter fullscreen mode Exit fullscreen mode

Lebih banyak tidak masalah selama setiap assertion memeriksa hal yang berbeda.

Apakah harus memeriksa seluruh response body secara persis?

Tidak selalu.

Gunakan exact match untuk field stabil:

$.status = paid
$.currency = IDR
Enter fullscreen mode Exit fullscreen mode

Gunakan existence/type check untuk field volatile:

$.id exists
$.created_at is datetime
Enter fullscreen mode Exit fullscreen mode

Hindari mencocokkan seluruh body jika berisi timestamp, UUID, atau field dinamis lain.

Bisakah performa API diuji dalam functional test?

Bisa. Tambahkan assertion response time:

response time < 800 ms
Enter fullscreen mode Exit fullscreen mode

Ini tidak menggantikan load testing, tetapi efektif untuk mendeteksi regresi latensi dasar.

Apakah negative test juga perlu assertion?

Ya. Negative test wajib punya assertion, terutama pada error body.

Contoh:

status = 400
$.error = validation_error
$.details berisi field yang salah
response tidak mengandung stack trace
response tidak mengandung data sensitif
Enter fullscreen mode Exit fullscreen mode

Tanpa ini, test hanya membuktikan API menolak request, bukan bahwa API menolak dengan format yang benar.

Kapan perlu menggunakan script assertion custom?

Gunakan script custom hanya jika visual assertion tidak cukup.

Contoh kebutuhan script:

membandingkan nilai dari dua response berbeda
menghitung checksum
validasi conditional berdasarkan response sebelumnya
membuat assertion dari data turunan
Enter fullscreen mode Exit fullscreen mode

Untuk assertion umum seperti status, schema, field body, header, dan response time, visual assertion biasanya lebih mudah dibaca, ditinjau, dan dipelihara.

Top comments (0)