7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. Web Development

Pengembangan JavaScript Didorong oleh Tes dalam Praktek

Scroll to top
Read Time: 20 mins

Indonesian (Bahasa Indonesia) translation by Putri (you can also view the original English article)

TDD adalah proses pengembangan berulang di mana setiap iterasi dimulai dengan menulis tes yang merupakan bagian dari spesifikasi yang diterapkan. Iterasi singkat memungkinkan lebih banyak feedback instan pada kode yang ditulis, dan keputusan desain yang buruk lebih mudah ditangkap. Dengan menulis tes sebelum kode produksi apa pun, cakupan unit test yang baik datang dengan wilayah tersebut, tetapi itu hanyalah efek samping.

Tutorial yang Diterbitkan Ulang

Setiap beberapa minggu, kita mengunjungi kembali beberapa posting favorit pembaca dari sepanjang sejarah situs. Tutorial ini pertama kali diterbitkan pada November 2010.


Pembalikan Perkembangan

Dalam pemrograman tradisional, masalah diselesaikan dengan pemrograman sampai konsep sepenuhnya terwakili dalam kode. Idealnya, kode mengikuti beberapa pertimbangan desain arsitektur secara keseluruhan, meskipun dalam banyak kasus, mungkin terutama di dunia JavaScript, ini tidak terjadi. Gaya pemrograman ini memecahkan masalah dengan menebak-nebak kode apa yang diperlukan untuk menyelesaikannya, sebuah strategi yang dapat dengan mudah menyebabkan solusi kembung dan erat digabungkan. Jika tidak ada pengujian unit juga, solusi yang dihasilkan dengan pendekatan ini bahkan mungkin berisi kode yang tidak pernah dieksekusi, seperti logika penanganan kesalahan dan penanganan argumen "fleksibel", atau mungkin berisi kasus tepi yang belum diuji secara menyeluruh, jika diuji sama sekali.

Pengembangan yang digerakkan oleh tes mengubah siklus pengembangan menjadi terbalik. Alih-alih berfokus pada kode apa yang diperlukan untuk memecahkan masalah, pengembangan yang digerakkan tes dimulai dengan mendefinisikan tujuan. Tes unit membentuk spesifikasi dan dokumentasi untuk tindakan apa yang didukung dan dipertanggungjawabkan. Memang, tujuan TDD tidak menguji dan jadi tidak ada jaminan bahwa itu menangani mis. kasus tepi lebih baik. Namun, karena setiap baris kode diuji oleh sepotong kode sampel yang representatif, TDD cenderung menghasilkan lebih sedikit kode berlebih, dan fungsionalitas yang diperhitungkan cenderung lebih kuat. Pengembangan yang digerakkan pengujian yang tepat memastikan bahwa sistem tidak akan pernah berisi kode yang tidak dieksekusi.


Proses

Proses pengembangan yang digerakkan oleh tes adalah proses berulang di mana setiap iterasi terdiri dari empat langkah berikut:

  • Tulis ujian
  • Jalankan tes, perhatikan tes baru gagal
  • Buat lulus ujian
  • Refactor untuk menghapus duplikasi

Dalam setiap iterasi, tes adalah spesifikasinya. Setelah kode produksi yang cukup (dan tidak lebih) telah ditulis untuk lulus uji, kita selesai, dan kita dapat memperbaiki kode untuk menghapus duplikasi dan/atau meningkatkan desain, selama tes masih berlalu.


TDD Praktis: Pola Pengamat

Pola Observer (juga dikenal sebagai Publish/Subcribe, atau cukup pubsub) adalah pola desain yang memungkinkan kita untuk mengamati keadaan suatu objek dan diberitahu ketika itu berubah. Pola ini dapat memberikan objek dengan titik ekstensi yang kuat sambil mempertahankan kopling longgar.

Ada dua peran dalam The Observer - diamati dan pengamat. Pengamat adalah objek atau fungsi yang akan diberitahukan ketika keadaan diamati diamati. Observable memutuskan kapan untuk memperbarui pengamatnya dan data apa yang disediakan untuk mereka. Observable biasanya menyediakan setidaknya dua metode publik: pubsub, yang memberi tahu pengamatnya tentang data baru, dan pubsub yang mengikutsertakan pengamat ke acara.


Perpustakaan yang Dapat Diobservasi

Pengembangan yang digerakkan oleh tes memungkinkan kita untuk bergerak dalam langkah yang sangat kecil bila diperlukan. Dalam contoh dunia nyata pertama ini kita akan mulai dengan langkah-langkah terkecil. Saat kita mendapatkan kepercayaan pada kode dan prosesnya, kita akan secara bertahap meningkatkan ukuran langkah-langkah ketika keadaan memungkinkannya (yaitu, kode yang akan diterapkan cukup sepele). Menulis kode dalam iterasi kecil yang sering akan membantu kita merancang API sepotong demi sepotong serta membantu membuat lebih sedikit kesalahan. Ketika kesalahan terjadi, kita akan dapat memperbaikinya dengan cepat karena kesalahan akan mudah dilacak ketika menjalankan tes setiap kali kita menambahkan beberapa baris kode.


Menyiapkan Lingkungan

Contoh ini menggunakan JsTestDriver untuk menjalankan tes. Panduan pengaturan tersedia dari situs web resmi.

Tata letak proyek awal terlihat sebagai berikut:

File konfigurasi hanyalah konfigurasi JsTestDriver minimal:


Menambahkan Pengamat

Kita akan memulai proyek dengan menerapkan cara untuk menambahkan pengamat ke objek. Melakukan hal itu akan membawa kita melalui penulisan tes pertama, melihatnya gagal, lulus dengan cara paling kotor dan akhirnya refactoring itu menjadi sesuatu yang lebih masuk akal.


Tes Pertama

Tes pertama akan mencoba untuk menambahkan pengamat dengan memanggil metode addObserver. Untuk memverifikasi bahwa ini berfungsi, kita akan berterus terang dan menganggap bahwa observable menyimpan pengamatnya dalam sebuah array dan memeriksa bahwa pengamat adalah satu-satunya item dalam array itu. Tes ini termasuk dalam test/observable_test.js dan terlihat seperti berikut:


Menjalankan Tes dan Menontonnya Gagal

Sekilas, hasil menjalankan tes pertama kita sangat menghancurkan:


Membuat Test Pass

Jangan takut! Kegagalan sebenarnya adalah hal yang baik: Ia memberi tahu di mana harus memfokuskan upaya kita. Masalah serius pertama adalah bahwa tddj tidak ada. Mari kita tambahkan objek namespace di src/observable.js:

Menjalankan tes lagi menghasilkan kesalahan baru:

Kita dapat memperbaiki masalah baru ini dengan menambahkan konstruktor yang dapat diobservasi kosong:

Menjalankan tes sekali lagi membawa kita langsung ke masalah berikutnya:

Mari kita tambahkan metode yang hilang.

Dengan metode di tempat tes sekarang gagal di tempat array pengamat yang hilang.

Seaneh kelihatannya, sekarang saya akan mendefinisikan array pengamat di dalam metode pubsub. Ketika tes gagal, TDD menginstruksikan kami untuk melakukan hal paling sederhana yang mungkin bisa berhasil, tidak peduli seberapa kotor rasanya. Kita akan mendapat kesempatan untuk meninjau pekerjaan setelah tes lulus.


Refactoring

Saat mengembangkan solusi saat ini, kita telah mengambil rute tercepat ke tes kelulusan. Sekarang bilah berwarna, kita dapat meninjau solusi dan melakukan refactoring yang dianggap perlu. Satu-satunya aturan dalam langkah terakhir ini adalah menjaga bar hijau. Ini berarti kita harus melakukan refactor dalam langkah-langkah kecil juga, memastikan kita tidak sengaja merusak apapun.

Implementasi saat ini memiliki dua masalah yang harus kita tangani. Tes ini membuat asumsi terperinci tentang implementasi Observable dan implementasi addObserver di-kode untuk pengujian.

Kita akan membahas hard-coding terlebih dahulu. Untuk mengekspos solusi hard-coded, kita akan menambah tes untuk membuatnya menambahkan dua pengamat, bukan satu.

Seperti yang diharapkan, tes sekarang gagal. Tes mengharapkan fungsi yang ditambahkan sebagai pengamat harus menumpuk seperti elemen apa pun yang ditambahkan ke pubsub. Untuk mencapai ini, kita akan memindahkan instantiation array ke konstruktor dan cukup mendelegasikan addObserver ke push metode array:

Dengan implementasi ini di tempat tes lulus lagi, membuktikan bahwa kami telah mengurus solusi hard-coded. Namun, masalah mengakses properti publik dan membuat asumsi liar tentang implementasi Observable masih menjadi masalah. pubsub yang dapat diamati harus dapat diamati oleh sejumlah objek, tetapi tidak menarik bagi orang luar bagaimana atau di mana toko yang diamati menyimpannya. Idealnya, kita ingin dapat memeriksa dengan diamati jika pengamat tertentu terdaftar tanpa meraba-raba bagian dalamnya. Kita mencatat aroma dan melanjutkan. Nanti, kita akan kembali untuk meningkatkan tes ini.


Memeriksa Pengamat

Kita akan menambahkan metode lain ke Observable, hasObserver, dan menggunakannya untuk menghapus beberapa kekacauan yang ditambahkan saat menerapkan addObserver.


Tes

Metode baru dimulai dengan tes baru, dan perilaku berikutnya yang diinginkan untuk metode hasObserver.

Kita berharap tes ini gagal dalam menghadapi hasObserver yang hilang, yang ternyata berhasil.


Membuat Test Pass

Sekali lagi, kita menggunakan solusi paling sederhana yang dapat lulus tes saat ini:

Meskipun kita tahu ini tidak akan menyelesaikan masalah kami dalam jangka panjang, ini membuat tes tetap hijau. Mencoba untuk meninjau dan refactor membuat kita tidak punya tangan kosong karena tidak ada poin yang jelas di mana kita dapat meningkatkan. Tes adalah persyaratan kita, dan saat ini mereka hanya memerlukan hasObserver untuk mengembalikan true. Untuk memperbaikinya, kita akan memperkenalkan tes lain yang mengharapkan hasObserver untuk return false pengamat yang tidak ada, yang dapat membantu memaksa solusi nyata.

Tes ini gagal total, mengingat hasObserver selalu returns true, memaksa kita untuk menghasilkan implementasi nyata. Memeriksa apakah pengamat terdaftar adalah masalah sederhana untuk memeriksa bahwa array this.observers berisi objek yang semula diteruskan ke addObserver:

Metode Array.prototype.indexOf mengembalikan angka kurang dari 0 jika elemen tidak ada dalam array, jadi memeriksa bahwa itu mengembalikan angka sama dengan atau lebih besar dari 0 akan memberi tahu kita jika pengamat ada.


Mengatasi Ketidakcocokan Browser

Menjalankan tes di lebih dari satu browser menghasilkan hasil yang agak mengejutkan:

Internet Explorer versi 6 dan 7 gagal tes dengan pesan kesalahan paling umum: "Objek tidak mendukung properti atau metode ini". Ini dapat menunjukkan sejumlah masalah:

  • Kita memanggil metode pada objek yang null
  • Kita memanggil metode yang tidak ada
  • kita mengakses properti yang tidak ada

Untungnya, dalam langkah-langkah kecil, kita tahu bahwa kesalahan harus berhubungan dengan panggilan yang baru saja ditambahkan ke indexOf pada array pengamat kami. Ternyata, IE 6 dan 7 tidak mendukung metode JavaScript 1.6 Array.prototype.indexOf (yang tidak dapat benar-benar menyalahkannya, itu hanya baru-baru ini distandarisasi dengan ECMAScript 5, Desember 2009). Pada titik ini, kita memiliki tiga opsi:

  • Kurangi penggunaan Array.prototype.indexOf di hasObserver, secara efektif menduplikasi fungsi asli dalam mendukung browser.
  • Terapkan Array.prototype.indexOf untuk browser yang tidak mendukung. Sebagai alternatif, implementasikan fungsi pembantu yang menyediakan fungsionalitas yang sama.
  • Gunakan perpustakaan pihak ketiga yang menyediakan metode yang hilang, atau metode serupa.

Salah satu dari pendekatan ini yang paling cocok untuk menyelesaikan masalah yang diberikan akan tergantung pada situasi – mereka semua memiliki pro dan kontra. Demi menjaga agar Self-Contained mandiri, kita hanya akan mengimplementasikan hasObserver dalam hal loop di tempat panggilan indexOf, yang secara efektif mengatasi masalah. Kebetulan, itu juga tampaknya menjadi hal paling sederhana yang mungkin dapat bekerja pada titik ini. Jika kita mengalami situasi yang sama di kemudian hari, kita akan disarankan untuk mempertimbangkan kembali keputusan kita. hasObserver yang diperbarui terlihat sebagai berikut:


Refactoring

Dengan bilah kembali menjadi hijau, saatnya meninjau kemajuan. Kita sekarang memiliki tiga tes, tetapi dua di antaranya anehnya serupa. Tes pertama yang ditulis untuk memverifikasi kebenaran addObserver pada dasarnya menguji hal-hal yang sama dengan tes yang ditulis untuk memverifikasi Refactoring. Ada dua perbedaan utama antara dua tes: Tes pertama sebelumnya dinyatakan smelly, karena langsung mengakses array pengamat di dalam objek yang dapat diamati. Tes pertama menambahkan dua pengamat, memastikan keduanya ditambahkan. Kita sekarang dapat menggabungkan tes menjadi satu yang memverifikasi bahwa semua pengamat yang ditambahkan ke yang diamati benar-benar ditambahkan:


Memberitahu Pengamat

Menambahkan pengamat dan memeriksa keberadaan mereka bagus, tetapi tanpa kemampuan untuk memberi tahu mereka tentang perubahan yang menarik, Observable tidak terlalu berguna. Saatnya menerapkan metode notifikasi.


Memastikan Bahwa Pengamat Dipanggil

Tugas paling penting yang diberitahukan melakukan adalah memanggil semua pengamat. Untuk melakukan ini, kita perlu beberapa cara untuk memverifikasi bahwa pengamat telah dipanggil setelah fakta. Untuk memverifikasi bahwa suatu fungsi telah dipanggil, kita dapat mengatur properti pada fungsi ketika itu dipanggil. Untuk memverifikasi pengujian, kita dapat memeriksa apakah properti telah disetel. Tes berikut menggunakan konsep ini dalam tes pertama untuk memberi tahu.

Untuk lulus tes, kita perlu mengulang larik pengamat dan memanggil setiap fungsi:


Melewati Argumen

Saat ini para pengamat dipanggil, tetapi mereka tidak diberi data apa pun. Mereka tahu sesuatu terjadi - tetapi tidak harus apa. Kita akan membuat notifikasi mengambil sejumlah argumen, cukup meneruskannya kepada setiap pengamat:

Tes ini membandingkan argumen yang diterima dan lulus dengan menetapkan argumen yang diterima ke variabel lokal untuk tes. Pengamat yang baru saja kita buat sebenarnya adalah mata-mata tes manual yang sangat sederhana. Menjalankan tes mengonfirmasi bahwa itu gagal, yang tidak mengejutkan karena kita saat ini tidak menyentuh argumen di dalam pemberitahuan.

Untuk lulus ujian, kita dapat menggunakan aplikasi saat memanggil pengamat:

Dengan tes perbaikan sederhana ini kembali ke hijau. Perhatikan bahwa kita mengirimkan ini sebagai argumen pertama untuk diterapkan, yang berarti bahwa pengamat akan dipanggil dengan yang dapat diamati karena ini.


Penanganan Kesalahan

Pada titik ini Observable berfungsi dan kita memiliki tes yang memverifikasi perilakunya. Namun, tes hanya memverifikasi bahwa yang dapat diamati berperilaku benar dalam menanggapi input yang diharapkan. Apa yang terjadi jika seseorang mencoba mendaftarkan objek sebagai pengamat menggantikan fungsi? Apa yang terjadi jika salah satu pengamat meledak? Itu adalah pertanyaan yang perlu uji untuk menjawab. Memastikan perilaku yang benar dalam situasi yang diharapkan adalah penting – itulah yang paling sering dilakukan objek kita. Setidaknya supaya kita bisa berharap. Namun, perilaku yang benar bahkan ketika klien melakukan kesalahan sama pentingnya untuk menjamin sistem yang stabil dan dapat diprediksi.


Menambahkan Pengamat Bogus

Implementasi saat ini secara membabi buta menerima segala jenis argumen untuk addObserver. Meskipun implementasi kita dapat menggunakan fungsi apa pun sebagai pengamat, ia tidak dapat menangani nilai apa pun. Tes berikut ini mengharapkan yang dapat diamati untuk melemparkan pengecualian ketika mencoba untuk menambahkan pengamat yang tidak bisa dipanggil.

Dengan melempar pengecualian saat menambahkan pengamat, kita tidak perlu khawatir tentang data yang tidak valid nanti saat kita memberi tahu pengamat. Seandainya kita memprogram berdasarkan kontrak, kita dapat mengatakan bahwa prasyarat untuk metode addObserver adalah bahwa input harus dapat dipanggil. postcondition adalah bahwa pengamat ditambahkan ke yang dapat diobservasi dan dijamin akan dipanggil begitu panggilan yang diobservasi memberitahukan.

Tes gagal, jadi kita menggeser fokus untuk mendapatkan bar hijau lagi secepat mungkin. Sayangnya, tidak ada cara untuk memalsukan implementasi ini – melempar pengecualian pada setiap panggilan ke addObserver akan gagal semua tes lainnya. Untungnya, implementasinya cukup sepele:

addObserver sekarang memeriksa bahwa pengamat sebenarnya adalah fungsi sebelum menambahkannya ke daftar. Menjalankan tes menghasilkan perasaan sukses yang manis: Semuanya hijau.


Pengamat yang Berperilaku Tidak Baik

Observable sekarang menjamin bahwa setiap pengamat yang ditambahkan melalui addObserver dapat dipanggil. Namun, memberi tahu masih mungkin gagal mengerikan jika pengamat melempar pengecualian. Tes selanjutnya mengharapkan semua pengamat dipanggil meskipun salah satu dari mereka melempar pengecualian.

Menjalankan tes mengungkapkan bahwa implementasi saat ini meledak bersama dengan pengamat pertama, menyebabkan pengamat kedua tidak dipanggil. Akibatnya, notifikasi melanggar jaminan bahwa ia akan selalu memanggil semua pengamat setelah mereka berhasil ditambahkan. Untuk memperbaiki situasi, metode yang perlu dipersiapkan untuk yang terburuk:

Pengecualian dibuang secara diam-diam. Adalah tanggung jawab pengamat untuk memastikan bahwa setiap kesalahan ditangani dengan benar, yang diamati hanya menangkis pengamat yang berperilaku buruk.


Mendokumentasikan Call Order

Kita telah meningkatkan kekokohan modul Observable dengan memberikannya penanganan kesalahan yang tepat. Modul ini sekarang dapat memberikan jaminan operasi selama mendapat input yang baik dan dapat pulih jika pengamat gagal memenuhi persyaratannya. Namun, tes terakhir yang ditambahkan membuat asumsi pada fitur yang tidak terdokumentasi dari yang dapat diamati: Ini mengasumsikan bahwa pengamat dipanggil dalam urutan yang ditambahkan. Saat ini, solusi ini berfungsi karena kita menggunakan array untuk mengimplementasikan daftar pengamat. Namun, jika kita memutuskan untuk mengubah ini, tes kita mungkin rusak. Jadi kita perlu memutuskan: apakah kita menolak tes untuk tidak menerima pesanan panggilan, atau apakah kita hanya menambahkan tes yang mengharapkan pesanan panggilan –dengan demikian mendokumentasikan pesanan panggilan sebagai fitur? Urutan panggilan sepertinya fitur yang masuk akal, jadi pengujian berikutnya akan memastikan Observable menjaga perilaku ini.

Karena implementasi sudah menggunakan array untuk pengamat, tes ini berhasil segera.


Mengamati Objek Sewenang-wenang

Dalam bahasa statis dengan warisan klasik, objek sewenang-wenang dibuat dapat diobservasi dengan mensubkelas kelas Observable. Motivasi untuk pewarisan klasik dalam kasus-kasus ini berasal dari keinginan untuk mendefinisikan mekanisme pola di satu tempat dan menggunakan kembali logika di sejumlah besar objek yang tidak terkait. Dalam JavaScript, kita memiliki beberapa opsi untuk menggunakan kembali kode di antara objek, jadi tidak perlu membatasi diri pada persaingan model warisan klasik.

Untuk membebaskan diri dari persaingan klasik yang disediakan oleh konstruktor, perhatikan contoh berikut yang mengasumsikan bahwa tddjs.observable adalah objek daripada konstruktor:

Catatan: Metode tddjs.extend diperkenalkan di tempat lain dalam buku ini dan cukup menyalin properti dari satu objek ke objek lainnya.

Cukup menerapkan objek yang dapat diamati sebagai satu objek menawarkan banyak fleksibilitas. Untuk sampai di sana kita perlu memperbaiki solusi yang ada untuk menyingkirkan konstruktor.


Membuat Constructor Usang

Untuk menghilangkan konstruktor, pertama-tama kita harus refactor diamati sehingga konstruktor tidak melakukan pekerjaan apa pun. Untungnya, konstruktor hanya menginisialisasi array pengamat, yang seharusnya tidak terlalu sulit untuk dihapus. Semua metode di Observable.prototype mengakses array, jadi kita perlu memastikan mereka semua bisa menangani case yang belum diinisialisasi. Untuk menguji ini, kita hanya perlu menulis satu tes per metode yang memanggil metode tersebut sebelum melakukan hal lain.

Karena kita sudah memiliki tes yang memanggil addObserver dan hasObserver sebelum melakukan hal lain, kita akan berkonsentrasi pada metode notify. Metode ini hanya diuji setelah addObserver dipanggil. Tes kita berikutnya mengharapkan untuk memanggil metode ini sebelum menambahkan pengamat.

Dengan tes ini di tempat kita dapat mengosongkan konstruktor:

Menjalankan tes menunjukkan bahwa semua kecuali satu sekarang gagal, semua dengan pesan yang sama: "pengamat ini tidak didefinisikan". Kita akan berurusan dengan satu metode pada satu waktu. Pertama adalah metode addObserver:

function addObserver(observer) {
if (!this.observers) {
this.observers = [];
}

/* ... */
}

Menjalankan tes lagi mengungkapkan bahwa metode addObserver yang diperbarui memperbaiki semua kecuali dua tes yang tidak dimulai dengan memanggilnya. Selanjutnya, kita memastikan untuk mengembalikan false langsung dari hasObserver jika array tidak ada.

Kita dapat menerapkan perbaikan yang sama persis untuk memberi tahu:


Memasang Kembali Konstruktor dengan Objek

Sekarang constructor tidak melakukan apa-apa, itu dapat dihapus dengan aman. Kita kemudian akan menambahkan semua metode secara langsung ke object tddjs.observable, yang kemudian dapat digunakan dengan mis. Object.create atau tddjs.extend untuk membuat objek yang bisa diamati. Perhatikan bahwa nama tersebut tidak lagi ditulis dengan huruf besar karena tidak lagi merupakan konstruktor. Implementasi yang diperbarui berikut:

Tentunya, melepas konstruktor menyebabkan semua tes sejauh ini rusak. Namun, memperbaikinya mudah. Yang perlu kita lakukan adalah mengganti pernyataan baru dengan panggilan ke Object.create. Namun, sebagian besar browser belum mendukung Object.create, sehingga kita dapat menguranginya. Karena metode ini tidak mungkin untuk ditiru dengan sempurna, kita akan memberikan versi sendiri pada object tddjs:

Dengan shim di tempatnya, kita dapat memperbarui tes dalam masalah yang akan berfungsi bahkan di browser lama. Paket tes akhir berikut:

Untuk menghindari duplikasi panggilan tddjs.create, setiap test case memperoleh method setUp yang mengatur observable untuk pengujian. Metode pengujian harus diperbarui sesuai, menggantikan diamati dengan ini. Diobservasi.


Ringkasan

Test-Driven JavaScript Development
Melalui kutipan dari buku ini, kita memiliki pengantar lunak untuk Pengembangan Test-Driven with JavaScript. Tentu saja, API saat ini terbatas dalam kemampuannya, tetapi buku ini memperluas lebih lanjut dengan memungkinkan pengamat untuk mengamati dan memberi tahu acara khusus, seperti observable.observe( "beforeLoad", myObserver).

Buku ini juga memberikan wawasan tentang bagaimana Anda dapat menerapkan TDD untuk mengembangkan kode yang mis. sangat bergantung pada manipulasi DOM dan Ajax, dan akhirnya menyatukan semua proyek sampel dalam aplikasi obrolan berbasis browser yang berfungsi penuh.

Kutipan ini didasarkan pada buku, 'Pengembangan JavaScript Didorong-Tes', yang ditulis oleh Christian Johansen, diterbitkan oleh Pearson / Addison-Wesley Professional, September 2010, ISBN 0321683919, Hak Cipta 2011 Pearson Education, Inc. Lihat di sini untuk Tabel selengkapnya Isi

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.