Lingkungan pengujian

Seperti yang diperkenalkan dalam Pengertian pengujian, pengujian dalam JavaScript pada dasarnya hanyalah kode yang telah kami konfirmasi berhasil dijalankan, yaitu tanpa menampilkan Error. Namun, salah satu cara penyederhanaan yang berlebihan adalah dengan tidak mempertimbangkan tempat kita menjalankan kode, lingkungan pengujian-nya.

Lingkungan pengujian secara luas dapat dianggap sebagai dua komponen: lingkungan runtime yang Anda gunakan untuk menjalankan pengujian (seperti Node, atau browser) serta API yang tersedia untuk Anda.

Lingkungan runtime

Runtime seperti Node, atau alat serupa seperti Deno atau Bun, ditujukan untuk mendukung kode JS sisi server atau tujuan umum. Lingkungannya tidak menyertakan API yang mungkin Anda harapkan di browser, seperti membuat dan menggunakan elemen DOM dan HTML, atau konsep apa pun terkait komponen visual atau target render (yaitu, bukan elemen hanya, tetapi merender elemen tersebut secara visual bersama CSS ke area pandang).

Dengan demikian, runtime tujuan umum ini akan gagal jika Anda mencoba, misalnya, merender elemen React agar dapat diuji, karena tidak ada objek document atau window yang tersedia.

Di sisi lain, jika Anda menjalankan pengujian di dalam browser, API bawaan yang dapat Anda harapkan dari runtime ini mungkin tidak tersedia tanpa polyfill atau beberapa pekerjaan tambahan. Gotcha yang umum adalah membaca dan menulis file: tidak mungkin untuk import { fs } from 'node:'fs'; di dalam browser dan membaca file dengan cara ini sebagai bagian dari pengujian.

Masalah API "web" versus "backend" ini sedikit di luar cakupan pengujian, karena mungkin canggung memiliki codebase dengan bagian server dan klien, tetapi hal ini terkait dengan gagasan penulisan kode yang dapat diuji, yang akan kita lihat kembali selama kursus ini.

Menguji logika bisnis atau algoritma

Beberapa kode Anda tidak memerlukan impor Node atau browser untuk beroperasi, sehingga untuk diuji. Ini adalah hal yang akan kita bahas nanti dalam kursus ini, tetapi menyusun codebase Anda sedemikian rupa sehingga "logika bisnis" murninya terpisah dari rendering atau kode khusus Node dapat mempermudah pengujian.

Untuk contoh singkat, Anda mungkin memiliki fungsi Node yang membaca dan menulis file dari disk, lalu memodifikasinya dalam prosesnya. Dengan memfaktorkan ulang fungsi guna menerima fungsi yang menjalankan baca dan tulis dari disk, berarti Anda membuatnya dapat diuji di mana saja.

Dalam hal ini, Anda dapat menggunakan lingkungan apa pun untuk menguji kode ini, baik dalam runtime sisi server atau browser. Dalam pengujian, Anda dapat menyediakan helper yang menyimpan file virtual dalam memori atau menampilkan data placeholder. Helper semacam ini boleh diperkenalkan dalam pengujian, karena tidak penting untuk memeriksa, misalnya, bahwa fs.writeFileSync berfungsi. Fokus pada kode Anda dan apa yang membuatnya unik atau berisiko.

Emulasi API browser

Banyak framework pengujian, seperti Vitest, memberi Anda opsi untuk mengemulasi lingkungan API browser tanpa menjalankan browser. Vitest secara internal menggunakan library yang disebut JSDOM. Ini dapat menjadi pilihan yang baik untuk pengujian komponen sederhana dengan overhead penggunaan browser yang tinggi.

Fitur umum dari library emulasi adalah, meskipun library emulasi dapat mengemulasi browser—misalnya, DOM, elemen, dan cookie, library tersebut tidak memiliki komponen visual. Artinya, keduanya akan menyediakan cara penting untuk menggunakan elemen HTML dan primitif lainnya, tetapi Anda tidak dapat merender output ke gambar atau layar, atau memeriksa posisi elemen dalam piksel pada halaman.

Sekali lagi, pilihan ini mungkin sangat cocok untuk pengujian komponen, dengan komponen mewakili elemen React, atau Komponen Web, atau sebagainya. Jenis komponen ini biasanya membuat dan berinteraksi dengan DOM dengan cara yang relatif kecil, dan browser yang diemulasi dapat menyediakan fungsi yang cukup untuk mengonfirmasi komponen berfungsi seperti yang Anda inginkan. Bagian selanjutnya mencakup contoh pengujian komponen React dengan Vitest dan JSDOM.

Mengemulasi browser adalah praktik yang sudah umum. JSDOM dirilis pada tahun 2014, tetapi akan selalu berbeda dengan penggunaan browser sebenarnya. Perbedaan ini bisa terlihat jelas: misalnya, JSDOM tidak menyertakan mesin tata letak, sehingga tidak ada cara untuk memeriksa ukuran elemen atau menguji gestur yang kompleks seperti menggeser. Perbedaannya juga bisa jadi halus dan tidak diketahui. Itulah sebabnya pengujian berbasis JSDOM sebaiknya tetap ringkas, sehingga Anda dapat 'timebox' risiko bahwa perilaku apa pun menyimpang dari yang sebenarnya.

Mengontrol browser sungguhan

Untuk menguji kode Anda sebagaimana pengguna akan mencobanya, menggunakan browser sungguhan adalah pilihan terbaik. Dalam praktiknya, menguji runtime yang mendukung browser akan memulai dan mengontrol instance browser sebenarnya, meskipun runtime tersebut berjalan 'start' di dalam Node.js.

Dengan mengontrol browser sebagai bagian dari pengujian, browser akan terbuka seperti yang dilakukan pengguna, sehingga pengujian Anda dapat mengontrolnya dengan memuat URL, HTML dan JS kustom, atau apa pun yang diperlukan untuk melakukan pengujian. Selanjutnya, Anda dapat menulis kode untuk bertindak sebagai pengguna, misalnya dengan mengontrol mouse atau mengetik input ke dalam kotak input.

Alat modern seperti WebdriverIO atau Web Test Runner dapat mengontrol semua browser utama, dan bahkan menjalankan beberapa instance secara bersamaan. Browser ini dapat berjalan berdekatan dengan runner pengujian (misalnya, di komputer Anda sendiri, atau sebagai bagian dari tindakan CI), atau dialihdayakan ke layanan komersial eksternal yang akan menjalankannya untuk Anda.

Library pengujian yang lebih mapan (termasuk Vitest dan Jest) sering kali memiliki mode browser. Namun, karena asalnya berasal dari Node.js, mode browsernya sering "dipasang" dan tidak memiliki fitur yang berguna. Misalnya, Vitest tidak dapat tiru impor modul di browser, yang merupakan primitif canggih yang kita gunakan dalam contoh di halaman berikutnya.

Dalam praktik

Dengan semakin kompleksnya pengujian, penggunaan browser sungguhan menjadi semakin penting.

  • Untuk pengujian yang tidak menggunakan fitur minimal atau tidak menggunakan DOM, bahkan fitur yang tersedia di Node.js dan runtime serupa, seperti fetch atau EventTarget, lingkungannya tidak menjadi masalah.
  • Untuk pengujian komponen kecil, JSDOM bisa saja cocok.
  • Pengujian yang lebih besar—misalnya, pengujian menyeluruh, yang dapat menyimulasikan pengguna yang login dan melakukan tindakan inti—masuk akal untuk berjalan sepenuhnya di browser sungguhan.

Bagian ini terlalu banyak membahas teori dan menyajikan sudut pandang berbeda tentang tempat untuk menjalankan pengujian. Dalam praktiknya, codebase Anda akan sering menggunakan banyak pendekatan berbeda terhadap berbagai jenis pengujian berdasarkan kebutuhan Anda dan apa yang disediakan alat pengujian.

Menguji pemahaman Anda

Fitur browser apa yang *tidak* didukung oleh lapisan emulasi jsdom?

Mesin tata letak.
Karena bukan alat visual, JSDOM tidak dapat digunakan untuk memeriksa posisi elemen pada halaman, atribut CSS yang di-resolve, atau bagian lainnya dari tata letak situs.
WebSocket
JSDOM mencakup polyfill WebSocket, sehingga kode yang menggunakannya juga dapat digunakan.
requestAnimationFrame
Dengan flag `pretendToBeVisual`, jsdom akan memanggil callback 'animasi' pada 60 fps, meskipun tidak ada yang benar-benar digambar.