Cara Menguji API Django REST Framework dengan Efektif

INEZA Felin-Michel

INEZA Felin-Michel

22 May 2026

Cara Menguji API Django REST Framework dengan Efektif

Apidog untuk Perusahaan

Penerapan On-Premises

SSO & RBAC

Sesuai SOC 2

Jelajahi Apidog Enterprise

Django REST Framework, biasanya disingkat DRF, adalah perangkat standar untuk membangun API di atas Django. Ini memberi Anda serializer, viewset, router, dan lapisan autentikasi. Apa yang juga diberikannya kepada Anda, dan yang banyak diremehkan oleh pengembang, adalah lapisan pengujian yang solid yang dibangun di atas *test runner* Django sendiri.

Panduan ini menunjukkan cara menguji API DRF dengan dua cara. Pertama, pengujian otomatis yang ditulis dalam Python menggunakan APITestCase dan APIClient dari DRF, yang berjalan tanpa server langsung dan menangkap regresi di setiap *commit*. Kedua, melatih *endpoint* yang berjalan dengan klien API, yaitu bagaimana Anda menjelajahi perilaku dan memverifikasi layanan yang sebenarnya. Keduanya penting, dan keduanya menangkap masalah yang berbeda.

Siapkan proyek dan lingkungan pengujian

Mulai dengan lingkungan terisolasi agar dependensi pengujian tetap terpisah dari sisa sistem Anda:

python -m venv venv
source venv/bin/activate
pip install django djangorestframework coverage

Proyek DRF diuji seperti proyek Django lainnya. Berdasarkan konvensi, pengujian berada dalam file tests.py di dalam setiap aplikasi, atau dalam paket tests/ jika Anda memiliki banyak pengujian. *Test runner* Django menemukan setiap kelas yang merupakan subkelas dari varian TestCase dan setiap metode yang namanya dimulai dengan test_.

Pilihan utama adalah kelas dasar mana yang akan digunakan. unittest.TestCase biasa tidak memiliki basis data. TestCase Django membungkus setiap pengujian dalam transaksi dan mengembalikannya (*rolls it back*), sehingga pengujian tidak saling mengganggu. APITestCase DRF memperluas TestCase Django dan mengganti klien dengan APIClient DRF, yang memahami autentikasi dan tipe konten DRF. Untuk pekerjaan API, gunakan APITestCase.

Satu kelas lagi yang patut diketahui adalah TransactionTestCase. Ini tidak membungkus pengujian dalam transaksi, yang Anda butuhkan ketika kode yang diuji mengelola transaksi itu sendiri atau bergantung pada fitur basis data yang akan disembunyikan oleh transaksi pembungkus. Ini lebih lambat karena memotong tabel di antara pengujian alih-alih mengembalikan (*rolling back*), jadi gunakan hanya ketika TestCase benar-benar tidak dapat memodelkan perilaku tersebut. Untuk sebagian besar pengujian *endpoint*, APITestCase adalah pilihan yang tepat dan tercepat.

Penting juga untuk memikirkan data pengujian sejak awal. Gunakan metode setUp untuk membuat baris yang dibutuhkan setiap pengujian dalam sebuah kelas, atau setUpTestData jika data bersifat *read-only* dan dapat dibagikan di seluruh kelas untuk kecepatan. Untuk proyek yang lebih besar, pustaka *factory* seperti factory_boy menghasilkan instans model yang valid tanpa Anda harus menyebutkan setiap bidang, yang membuat pengujian tetap ringkas dan tangguh ketika sebuah model mendapatkan bidang wajib baru.

Uji serializer sebagai unit

Serializer melakukan validasi dan mengonversi antara instans model dan JSON. Mereka kecil dan murni, yang membuatnya ideal untuk pengujian unit cepat yang tidak menyentuh *endpoint*.

Misalkan Anda memiliki model Article dan ArticleSerializer. Pengujian unit memeriksa bahwa data yang valid lolos dan data yang tidak valid gagal:

from django.test import TestCase
from articles.serializers import ArticleSerializer


class ArticleSerializerTests(TestCase):

    def test_valid_data_passes(self):
        data = {"title": "Caching strategies", "body": "Use ETags."}
        serializer = ArticleSerializer(data=data)
        self.assertTrue(serializer.is_valid())

    def test_missing_title_fails(self):
        data = {"body": "No title here."}
        serializer = ArticleSerializer(data=data)
        self.assertFalse(serializer.is_valid())
        self.assertIn("title", serializer.errors)

Pengujian ini berjalan dalam milidetik karena tidak ada HTTP dan tidak ada *view*. Mereka memberi tahu Anda bahwa aturan validasi sudah benar bahkan sebelum Anda mempertimbangkan *endpoint*. Cakupan tingkat unit ini adalah dasar dari piramida pengujian yang dijelaskan dalam apa itu pengujian otomatis.

Uji endpoint dengan APITestCase dan APIClient

Pengujian *endpoint* memeriksa jalur lengkap: *routing*, *view*, serializer, dan respons. APIClient DRF mengirimkan permintaan secara *in-process*, sehingga tidak ada server yang berjalan dan pengujian tetap cepat.

from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from articles.models import Article


class ArticleEndpointTests(APITestCase):

    def setUp(self):
        Article.objects.create(title="First post", body="Hello world")

    def test_list_articles_returns_200(self):
        url = reverse("article-list")
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data), 1)

    def test_create_article(self):
        url = reverse("article-list")
        payload = {"title": "Second post", "body": "More content"}
        response = self.client.post(url, payload, format="json")
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(Article.objects.count(), 2)

Beberapa detail yang perlu diperhatikan. self.client adalah instans APIClient yang disediakan oleh APITestCase. Gunakan reverse() dengan nama rute alih-alih mengkodekan URL secara langsung, agar perubahan rute tidak merusak setiap pengujian. Berikan format="json" pada operasi tulis agar klien menserialisasi *payload* dengan benar. Pastikan kode status dengan konstanta bernama dari rest_framework.status, karena lebih mudah dibaca daripada angka mentah. Kode status itu sendiri dibahas dalam panduan tentang kode status HTTP yang harus digunakan API REST.

Uji autentikasi dan izin

Sebagian besar API nyata melindungi *endpoint*-nya. Anda memerlukan pengujian yang membuktikan bahwa permintaan yang tidak diautentikasi ditolak dan permintaan yang diautentikasi dengan izin yang benar berhasil.

APIClient menawarkan dua cara untuk mengautentikasi pengujian. force_authenticate() melewatkan pemeriksaan kredensial dan melampirkan pengguna secara langsung, yang ideal untuk menguji logika *view* itu sendiri. login() atau credentials() menjalankan jalur autentikasi yang sebenarnya. Berikut adalah pengujian izin menggunakan kedua arah:

from django.contrib.auth.models import User
from rest_framework import status
from rest_framework.test import APITestCase
from django.urls import reverse


class ArticlePermissionTests(APITestCase):

    def setUp(self):
        self.user = User.objects.create_user(
            username="editor", password="testpass123"
        )
        self.url = reverse("article-list")

    def test_anonymous_cannot_create(self):
        payload = {"title": "Blocked", "body": "Should fail"}
        response = self.client.post(self.url, payload, format="json")
        self.assertEqual(
            response.status_code, status.HTTP_403_FORBIDDEN
        )

    def test_authenticated_user_can_create(self):
        self.client.force_authenticate(user=self.user)
        payload = {"title": "Allowed", "body": "Should pass"}
        response = self.client.post(self.url, payload, format="json")
        self.assertEqual(
            response.status_code, status.HTTP_201_CREATED
        )

Pengujian pertama mengonfirmasi bahwa kelas izin memblokir penulisan anonim. Yang kedua mengonfirmasi bahwa pengguna yang diautentikasi berhasil. Bersama-sama, mereka mengunci batas izin, yang merupakan jenis perilaku yang secara diam-diam rusak selama *refactor*. Jika Anda menguji autentikasi token secara khusus, ganti force_authenticate dengan self.client.credentials(HTTP_AUTHORIZATION="Token " + token) untuk melatih jalur *header* yang sebenarnya.

Perlu disengaja mengenai mana yang akan digunakan. force_authenticate lebih cepat dan mengisolasi logika *view*, sehingga cocok untuk sebagian besar pengujian izin di mana Anda hanya peduli bahwa suatu peran dapat atau tidak dapat melakukan sesuatu. Jalur kredensial yang sebenarnya adalah apa yang Anda inginkan untuk kumpulan pengujian yang lebih kecil yang secara khusus membuktikan mekanisme autentikasi berfungsi: bahwa token yang buruk ditolak, bahwa token yang kedaluwarsa gagal, bahwa *endpoint* masuk mengeluarkan token yang dapat digunakan. Mencampur keduanya memberi Anda cakupan luas secara murah dan cakupan mendalam di mana itu penting.

Jangan lupakan izin tingkat objek. Banyak API DRF mengizinkan pengguna untuk mengedit catatan mereka sendiri tetapi bukan catatan orang lain. Uji secara eksplisit: buat dua pengguna, minta satu pengguna membuat catatan, lalu pastikan pengguna lain mendapatkan 403 atau 404 saat mencoba memodifikasinya. *Endpoint* daftar layak mendapat pengawasan yang sama, karena *queryset* yang bocor dapat mengembalikan baris yang seharusnya tidak pernah dilihat pengguna bahkan ketika *endpoint* detail dikunci.

Jalankan suite dan ukur cakupan

Jalankan setiap pengujian dengan *runner* Django:

python manage.py test

*Runner* menemukan kelas pengujian Anda, menyiapkan basis data pengujian sementara, menjalankan setiap pengujian di dalam transaksi, dan mengembalikan (*rollback*) setelahnya. Jika berhasil, akan tercetak OK. Jika gagal, akan ditampilkan *assertion* yang rusak dan di mana.

Mengetahui bahwa *suite* berhasil tidak sama dengan mengetahui bahwa ia mencakup cukup. Alat coverage mengukur baris mana yang benar-benar dijalankan:

coverage run --source='.' manage.py test
coverage report
coverage html

Laporan mencantumkan setiap file dengan persentase baris yang dijalankan. Output HTML menyoroti baris yang belum diuji dengan warna merah, yang langsung menunjukkan celah. Targetkan cakupan yang berarti untuk *view*, serializer, dan izin daripada hanya satu angka utama. Artikel tentang cara menulis skrip pengujian otomatis membahas apa yang membuat pengujian layak dipertahankan, karena cakupan pengujian yang lemah bukanlah keamanan nyata.

Uji API langsung dengan klien

Pengujian Python otomatis cepat dan berjalan di CI, tetapi mereka melatih aplikasi secara *in-process*. Mereka tidak menangkap masalah yang hanya muncul terhadap layanan yang berjalan: *header* CORS yang salah konfigurasi, *reverse proxy* yang menghilangkan sesuatu, basis data yang lambat di bawah beban nyata, atau perbedaan antara basis data pengujian Anda dan produksi. Untuk itu Anda mengirimkan permintaan nyata ke *endpoint* yang di-deploy.

Apidog sangat cocok di sini. Ini adalah platform API *all-in-one*, sehingga Anda dapat mengimpor skema OpenAPI API DRF Anda, mengirim permintaan langsung ke server yang sedang berjalan, dan membangun *assertion* secara visual tanpa menulis lebih banyak Python. DRF dapat menghasilkan skema OpenAPI, dan Apidog mengonsumsinya secara langsung, yang menjaga klien Anda tetap sinkron dengan kontrak sebenarnya. Anda juga dapat membangun skenario pengujian multi-langkah, misalnya masuk, membuat artikel, mengambilnya, menghapusnya, dan menjalankannya sesuai jadwal atau di CI. Ini melengkapi *suite* APITestCase Anda daripada menggantikannya: pengujian unit dan *endpoint* menjaga kode, klien API menjaga layanan yang di-deploy. Anda dapat mengunduh Apidog untuk mengimpor skema DRF dan mencobanya. Untuk tim yang lebih memilih tetap menggunakan Python dari awal hingga akhir, panduan kerangka pengujian otomatis API pytest menunjukkan cara menjalankan pengujian gaya DRF di bawah pytest.

Pertanyaan yang sering diajukan

Apa perbedaan antara TestCase dan APITestCase?

TestCase Django membungkus setiap pengujian dalam transaksi basis data dan memberi Anda klien pengujian Django standar. APITestCase DRF adalah subkelasnya dan mengganti klien dengan APIClient, yang memahami skema autentikasi DRF, negosiasi konten, dan argumen format pada permintaan. Gunakan APITestCase untuk menguji *endpoint* DRF.

Kapan saya harus menggunakan force_authenticate daripada login?

Gunakan force_authenticate() ketika Anda ingin menguji logika *view* dan izin tanpa biaya dan kompleksitas alur kredensial yang sebenarnya. Ini melampirkan pengguna ke permintaan secara langsung. Gunakan login() atau credentials() ketika mekanisme autentikasi itu sendiri, seperti sesi atau autentikasi token, adalah yang ingin Anda verifikasi.

Apakah pengujian DRF memerlukan server yang berjalan?

Tidak. APIClient mengirimkan permintaan secara *in-process* langsung ke *view* Anda, sehingga *suite* pengujian berjalan tanpa memulai server. Itulah yang membuatnya cepat. Untuk menguji layanan yang benar-benar di-deploy, termasuk infrastruktur seperti *proxy* dan CORS, Anda mengirimkan permintaan HTTP nyata dengan klien API seperti Apidog.

Bagaimana cara memeriksa cakupan pengujian untuk proyek DRF?

Instal paket coverage, lalu jalankan coverage run --source='.' manage.py test diikuti dengan coverage report untuk ringkasan atau coverage html untuk tampilan baris per baris. Laporan HTML menyoroti baris yang belum diuji sehingga Anda dapat melihat dengan tepat *view* atau serializer mana yang kurang pengujian.

Haruskah saya menguji serializer dan endpoint secara terpisah?

Ya. Pengujian unit serializer cepat dan menunjukkan *bug* validasi tanpa *overhead* HTTP. Pengujian *endpoint* dengan APITestCase memeriksa *routing*, izin, dan siklus permintaan penuh. Menjaga keduanya memberi Anda umpan balik cepat di tingkat unit dan kepercayaan bahwa sambungan berfungsi di tingkat integrasi.

Mengembangkan API dengan Apidog

Apidog adalah alat pengembangan API yang membantu Anda mengembangkan API dengan lebih mudah dan efisien.