js pengujian. Tes Pengetahuan JavaScript - Dasar-dasar

Seorang teman saya pernah mengungkapkan kebingungannya tentang bagaimana JavaScript dapat digunakan untuk menulis produk perusahaan yang serius, karena tidak memiliki kompiler. Faktanya, peran yang menentukan dalam membuat kode berkualitas tinggi sama sekali tidak dimainkan oleh fakta memiliki kompiler untuk bahasa pemrograman, tetapi oleh proses teknis yang dipilih dengan benar dan disetel dengan baik untuk membuat sistem perangkat lunak.

Proses ini harus mencakup seperangkat alat kontrol kualitas dan efisiensi untuk pemrogram. Alat tersebut dapat berupa: pengujian unit dan integrasi, integrasi berkelanjutan (Integrasi Berkelanjutan, CI), pengumpulan dan analisis berbagai metrik (misalnya, metode yang sangat panjang di nDepend), memeriksa kepatuhan terhadap persyaratan JsLint, FxCop, dll.

Pada artikel ini, saya ingin memberi tahu Anda cara melakukan pengujian unit dan integrasi otomatis dengan benar pada produk Anda di JavaScript. Faktanya, JavaScript tidak berbeda dengan Java atau C# dalam hal ini.

Lincah, TDD dan BDD

Umumnya disarankan untuk membuat pengujian unit dan integrasi otomatis untuk fungsionalitas yang dijalankan untuk mengurangi risiko kesalahan regresi saat mengubah kode di masa mendatang. Dalam kasus JavaScript, pengujian ini dapat mempermudah verifikasi bahwa sistem berfungsi di berbagai browser dengan mengotomatiskan langkah-langkah untuk memastikannya berfungsi. Selain itu, menulis tes unit atau integrasi untuk setiap bug yang ditutup dalam produk dapat memberikan layanan yang baik.

Ada juga teknik pemrograman yang mengharuskan Anda memulai pengkodean logika dengan menulis unit test: Test-Driven Development (TDD) dan Behavior-Driven Development (BDD). Mereka sering digunakan dalam proses Agile. Mari pertimbangkan fitur mereka secara lebih rinci.

Pengembangan Berbasis Tes

Pengembangan berbasis tes adalah proses pengkodean berulang yang mengulangi empat langkah berikut:

Langkah 1. Sebelum menambahkan logika baru, buat pengujian unit untuk menguji logika tersebut;

Langkah 2. Jalankan tes dan pastikan itu Bukan melewati;

Langkah 3. Tulis kode paling sederhana yang akan lulus ujian;

Langkah 4. Edit kode sesuai dengan persyaratan kualitas, hapus duplikasi kode, dan pastikan tes lulus.

Tes unit adalah kode yang menguji pengoperasian beberapa komponen (modul) di lingkungan yang terisolasi. Tes integrasi adalah kode yang menguji kerja sama beberapa komponen. Tes ganda digunakan untuk menguji modul di lingkungan yang terisolasi ketika tergantung pada modul lain.

Tes Ganda

Pembagian objek bantu yang digunakan dalam pengujian unit ke dalam kategori berasal dari buku xUnit Test Patterns oleh Gerard Meszaros. Kategori-kategori ini secara kolektif disebut "tes ganda" (tes ganda). Pengganda adalah dari jenis berikut:

  • palsu;
  • Contoh.

Rintisan nilai keluaran yang telah ditetapkan sebelumnya. Ini digunakan untuk meniru antarmuka komponen yang bergantung.

Mengejek adalah objek pembantu perilaku yang diatur terlebih dahulu. Ini digunakan untuk meniru antarmuka komponen dependen dan menguji apakah digunakan dengan benar selama pengujian.

Mengintai adalah objek pembantu untuk memeriksa metode dan parameter yang dipanggil yang diteruskan ke mereka selama pengujian.

Palsu adalah objek pembantu yang mengimplementasikan antarmuka komponen dependen dalam bentuk yang disederhanakan. Misalnya, untuk tujuan pengujian unit, Anda dapat memiliki database dalam memori alih-alih database relasional yang digunakan dalam versi produksi produk.

Contoh adalah objek pembantu yang indikasi atau kelulusannya diperlukan oleh tanda tangan metode atau kontrak lainnya, tetapi nilai sebenarnya tidak pernah digunakan.

Perbedaan antara Stub dan Mock adalah bagaimana hasil tes diverifikasi. Dalam kasus Stub, status objek diperiksa pada akhir pengujian. Dalam kasus Mock, pengujian memeriksa apakah objek digunakan persis seperti yang dijelaskan saat pendaftaran. Detail dapat ditemukan di catatan Mocks Aren "t Stubs oleh Martin Fowler, dan saya akan memberikan contoh di sini saja.

Rintisan Mengejek
"test connect harus mulai polling": function () ( this.client.url = "/my/url"; sinon.stub(ajax, "poll").returns(()); this.client.connect(); sinon.menegaskan.dipanggilDengan(ajax.poll, "/my/url"); ) "test connect harus mulai polling": function () ( this.client.url = "/my/url"; var mock = sinon.mock(ajax) mock.expects("poll") .withArgs("/my/url ").returns(()); this.client.connect(); mock.verify(); )

Perkembangan Berbasis Perilaku

Pendekatan iteratif untuk pengembangan perangkat lunak melalui penerapan persyaratan fungsional - ini adalah gaya pengembangan berbasis pengujian yang sudah dikenal, berfokus pada hasil. Tiga langkah berikut diikuti secara berurutan dalam proses BDD:

Langkah 1. Definisi persyaratan fungsional untuk modul yang diimplementasikan dalam bentuk pengujian;

Langkah 2. Pengkodean modul;

Langkah 3. Memeriksa apakah semua keinginan pelanggan atau analis bisnis () dipenuhi dengan memeriksa hasil pengujian yang berjalan.

Saat menulis tes dalam gaya BDD, sangat mudah untuk menggunakan objek Mock karena fakta bahwa objek tersebut secara sempurna mencerminkan persyaratan fungsional untuk komponen tersebut. Dengan demikian, tes dalam proses BDD dapat berfungsi sebagai representasi tugas yang diformalkan ( cerita pengguna) dalam istilah scrum, yang memungkinkan Anda menghemat waktu untuk menulis spesifikasi teknis dan dokumentasi untuk produk jadi.

Apa yang seharusnya menjadi kerangka pengujian unit JavaScript?

Unit JavaScript yang lengkap dan alat pengujian integrasi harus terdiri dari komponen-komponen berikut:

  • Pustaka pernyataan (seperangkat metode untuk memeriksa status komponen di akhir setiap pengujian);
  • Pustaka Mock (alat untuk menghasilkan objek Mock dan "pengganti" lainnya);
  • Test runner (instrumen mulai otomatis pengujian dengan dukungan untuk sebagian besar browser, termasuk browser iOS dan Android);
  • Blok koneksi ke sistem populer integrasi berkelanjutan (Integrasi Berkelanjutan).

Strategi Pengujian Unit JavaScript

Saat ini, ada tiga strategi untuk pengujian unit kode JavaScript (untuk detail lebih lanjut, lihat bab ketiga buku Christian Johansen Test-Driven JavaScript Development):

  • di-browser pengujian;
  • tanpa kepala pengujian;
  • Menguji sepanjang jalan JsTestDriver.

Pengujian dalam Peramban melibatkan menjalankan semua pengujian unit dan integrasi dari laman HTML yang dibuka sendiri oleh pengembang di peramban yang diperlukan. Pendekatan ini sederhana dan intuitif. Namun, kerugiannya adalah tidak menyediakan kemungkinan untuk memasukkan pengujian semacam itu dalam Integrasi Berkelanjutan. Juga, meluncurkan halaman HTML secara manual di sepuluh atau lebih browser dan terus-menerus menekan "F5" bisa membosankan bagi pengembang.

Pengujian tanpa kepala berarti bahwa semua kode JavaScript diuji pada emulator, yang dapat ditulis dalam Java, Ruby, JavaScript, C++, dll. Emulator paling terkenal sejauh ini adalah PhantomJS, yang merupakan a webkit, diluncurkan dari garis komando. Di antara kelebihan emulator, dapat dicatat bahwa ini dapat dengan mudah digunakan dalam Integrasi Berkelanjutan, dan juga memungkinkan Anda untuk mengotomatiskan peluncuran semua pengujian dari baris perintah. Namun, pendekatan ini memiliki kekurangan yang signifikan - kode tidak diuji pada browser sebenarnya, sehingga ada risiko kesalahan browser yang hilang yang tidak direproduksi pada emulator. Sebelum munculnya JsTestDriver, Anda sering melihat pengujian In-Browser digabungkan dengan pengujian Headless, karena keduanya saling melengkapi dengan sangat baik.

Pengujian merupakan bagian integral dari siklus pengembangan perangkat lunak. Tim pengembangan pemula sering kali meremehkan perannya dan memeriksa kinerja aplikasi dengan cara lama - "berhasil, dan tidak apa-apa." Cepat atau lambat, strategi ini gagal dan pelacak bug mulai membanjiri pasukan tugas yang tak terhitung jumlahnya. Agar tidak jatuh ke dalam perangkap seperti itu, saya merekomendasikan sekali dan untuk selamanya untuk menangani nuansa pengujian kode JavaScript.

JavaScript bukan lagi kue!

Saya kira saya tidak perlu menjelaskan kepada Anda bahwa hari ini JavaScript bukan hanya bahasa untuk mempercantik. penampilan aplikasi. Tapi saya tetap akan menjelaskan dan membuat sedikit perkenalan, karena dengan begitu saya akan dibayar lebih uang lebih! 🙂 Jadi, saat JavaScript digunakan untuk bercanda atau membuat menu sudah hilang selamanya. Sekarang ini adalah bahasa independen yang bekerja dengan baik pada klien dan server. Peran JavaScript telah meningkat secara signifikan, artinya saat menulis kode, Anda tidak boleh malu menggunakan praktik yang telah terbukti sendiri dalam bahasa pemrograman lain.

Apa yang saya maksud dengan praktik dan paradigma? Tentu saja, pola arsitektur MVC (model view controller) dan pola organisasi kode. Dengan mengikuti trik sederhana ini, Anda akan dapat menulis kode yang lebih baik yang tidak hanya mudah dipelihara, tetapi juga memiliki kemampuan untuk diuji secara otomatis.

Aturan untuk tes yang baik

  • Tes harus sesederhana mungkin. Semakin sulit ujiannya, semakin besar kemungkinan untuk melakukan kesalahan.
  • Pengujian harus dikelompokkan ke dalam modul agar nantinya lebih mudah menemukan bug dan dapat menguji bagian tertentu dari aplikasi.
  • Setiap tes tidak boleh bergantung pada tes lainnya.
  • Selalu tulis tes terpisah setiap kali Anda menemukan bug.

Kesalahan sebagian besar penguji

Bukan rahasia lagi bahwa cara pengujian yang paling populer selalu menjadi tes mata yang dangkal. Esensinya sederhana untuk dipermalukan - saya menulis beberapa ribu baris kode, menyelesaikan masalah dan meluncurkan kreasi saya. Saya bermain-main, mengklik - semuanya tampak berfungsi, Anda dapat mengunggahnya ke server pertempuran. Semuanya sangat sederhana, dan dengan perhatian pengembang (idealnya, individu yang dijuluki "penguji"), Anda dapat mengandalkan pengoperasian aplikasi yang benar.

Dalam praktiknya, semuanya terjadi sedikit berbeda. Biasanya, tidak ada penguji terpisah. Pengembang sendiri mencoba memeriksa operabilitas program dengan melakukan urutan tindakan yang ditentukan dalam tugas teknis. Penempa kode yang lebih canggih mengotomatiskan pengujian integrasi semacam ini dengan alat seperti Selenium .

Dengan demikian, pemrogram mendapat kesempatan untuk mendeteksi hanya kesalahan yang paling besar. Sayangnya, tindakan pengguna yang "bodoh" dan "tak terduga", serta langkah rumit dalam logika bisnis dalam 99% kasus tetap berada di belakang layar.

Kehadiran penguji terpisah juga menyelesaikan masalah sebagian dan hingga waktu tertentu. Bahkan jika kita mengabaikan perhatian pencari ranjaunya terhadap detail, kualitas pengujiannya akan cenderung nol seiring berkembangnya aplikasi. Saya akan memberikan contoh dari latihan.

Suatu kali saya ditugaskan untuk mengembangkan program kecil. Dari segi fungsionalitas, proyek ini menyerupai CRM paling sederhana, yang saya terapkan dalam waktu sesingkat mungkin. Setelah menerima remunerasi yang jatuh tempo, saya menyerahkan semua sumber kepada pelanggan dan melupakan proyek tersebut selama delapan bulan. Kemudian yang paling menarik dimulai. Pelanggan memutuskan untuk secara serius memperluas fungsionalitas program dan menelepon saya untuk meminta bantuan. Secara alami, saya mengambilnya dan mulai memahat fungsi demi fungsi... Pada awalnya itu tidak sulit, tetapi ketika sampai pada integrasi fungsionalitas secara keseluruhan, segerombolan bug yang berdengung menyerbu ke arah saya. Potongan kode mulai bertentangan, dan saya harus menghabiskan banyak waktu untuk menyelesaikan konflik. “Nah, bagaimana Anda tidak melihat ada masalah dengan aplikasi Anda?” pembaca akan bertanya. Saya akan menjawab: Saya meluncurkannya, tetapi karena aplikasi telah berkembang, saya tidak punya waktu dan keberanian untuk menguji semua fungsionalitas secara massal. Saya membatasi diri hanya untuk menguji fungsi individual dan dengan murah hati membayarnya. Moral dari cerita ini: "Pikirkan pengujian sebagai bagian integral dari pengembangan."

Tes unit seperti peluru perak

Pengujian unit adalah cara terbaik untuk menyelamatkan saraf Anda dan meningkatkan jaminan bahwa setiap bagian dari aplikasi Anda akan berfungsi. Jika Anda belum pernah menjumpai binatang buas yang mengerikan ini, maka saya akan menjelaskannya secara singkat. Pengujian unit memungkinkan Anda mengotomatiskan proses pengujian dan mengekspos setiap fitur aplikasi Anda untuk pengujian.

Setelah selesai pembangunan fitur baru(dimungkinkan untuk menulis tes sebelum dimulainya pengembangan) pengembang menulis kode khusus untuk menguji kodenya. Perlu mensimulasikan situasi yang berbeda dan mengembalikan nilai. Misalnya, kami menulis fungsi untuk memangkas spasi (trim). Untuk menguji kinerjanya, kami harus menyiapkan beberapa pengujian yang memungkinkan kami untuk menyatakan bahwa:

  • saat meneruskan string "string" kita mendapatkan "string" sebagai output;
  • ketika melewati istilah "baris 9" pada output kita mendapatkan "baris 9";

Kami juga dapat menambahkan pengujian untuk parameter input lainnya (misalnya, mengganti karakter spasi dengan tab). Secara umum, semakin baik kita menutupi kode dengan pengujian dan semakin kita memperkirakan kemungkinan opsi negatif, semakin tinggi kemungkinan bahwa pada saat yang paling genting akan tersisa sedikit rambut di kepala.

Di dunia JS, tes biasanya ditulis menggunakan framework khusus. Mereka memiliki semua yang Anda butuhkan untuk ini, serta beberapa alat untuk mengatur laporan kemajuan pengujian.

Tests!= kode tambahan

Penguji non-unit suka berpendapat bahwa pengujian unit memerlukan penulisan dan pemeliharaan kode tambahan. Mereka mengatakan bahwa tenggat waktu dalam proyek nyata paling sering dikompresi dan tidak mungkin menulis kode tambahan.

Ketika tidak ada waktu untuk ujian

Jika tidak ada waktu, tidak masuk akal untuk menulis pengujian untuk fungsi sederhana (ambil trim () yang sama dari contoh di artikel), lebih baik fokus pada bagian kode yang paling kritis. Aturan yang sama harus diikuti saat menulis kode yang sering diubah. Kerangka acuan proyek langsung sering berubah, dan beberapa fitur harus terus diperbarui. Perubahan semacam itu dapat menyebabkan momen yang tidak menyenangkan - kode yang diubah berfungsi dengan baik dengan data baru, tetapi tidak mencerna data lama secara organik. Di sini, agar tidak menangkap kesalahan di sini, lebih baik segera periksa fungsi-fungsi tersebut. Ingat aturan sederhana: tidak ada waktu untuk menutupi semua kode dengan tes - tutupi bagian terpentingnya.


Mengenai tenggat waktu yang ketat, saya setuju, tetapi saya siap berdebat tentang bagian dari kode tambahan. Di satu sisi, ya - tes memerlukan kode tambahan, dan karenanya waktu untuk menulisnya. Di sisi lain, kode ini berperan sebagai kantung udara di dalam mobil dan pasti akan terbayar seiring bertambahnya aplikasi.
  • Cristian Johansen Test-Driven JavaScript Development (goo.gl/mE6Is) adalah salah satu dari sedikit buku yang membahas JavaScript dari perspektif penulisan tes.
  • John Resing, Beer Bibo JavaScript Ninja Secrets (goo.gl/xquDkJ) adalah buku bagus yang akan berguna terutama untuk pengembang JS menengah. Buku ini membahas secara rinci masalah penulisan kode lintas-browser yang efektif, nuansa penanganan acara, dan banyak kebaikan lainnya.
  • JavaScript David Flanagan. Panduan lengkap» (goo.gl/rZjjk) - Buku ini telah dicetak ulang enam kali dan setiap terbitannya menjadi bestseller. Memang, ini yang paling banyak panduan terperinci pada JavaScript, yang harus dibaca oleh setiap pengembang JS setidaknya sekali.
  • PhantomJS + JSCoverage + QUnit atau pengujian unit JS konsol dengan perhitungan cakupan (goo.gl/FyQ38) - penulis artikel mendemonstrasikan penggunaan sekumpulan paket di atas untuk mengumpulkan statistik dan menghitung persentase cakupan kode melalui pengujian.
  • Kasus Penggunaan PhantomJS yang Berguna - Halaman ini menunjukkan sejumlah besar penggunaan pertempuran PhantomJS.

Ketika tidak ada waktu dan keinginan untuk menolak tes tertulis sangat menyiksa, pikirkan tiga kali. Mungkin, dalam hal ini, akan lebih tepat untuk hanya mencakup bagian kode yang paling rumit dengan pengujian, daripada mengabaikan pengujian sepenuhnya. Selalu berpikir dengan pandangan ke masa depan, seolah-olah dalam sebulan program Anda dapat berkembang menjadi ukuran yang belum pernah terjadi sebelumnya.

Tidak semua kode diuji

Mengapa saya mengatakan bahwa Anda perlu memikirkan tentang pengujian sebelum menulis kode utama? Ya, karena kode yang seharusnya dicakup oleh pengujian unit ditulis dengan gaya yang sedikit berbeda. Tidak semua kode dapat diuji. Kode yang memadukan logika dan representasi, dan bahkan diisi Saya tidak mengerti di mana, tidak dapat diuji secara normal. Di sini saya selalu menyarankan Anda untuk mengikuti beberapa aturan sederhana:

  • Tidak perlu menulis fungsi besar. Setiap fungsi harus menyelesaikan satu masalah, bukan 100500 kemungkinan situasi. Misalnya, Anda tidak perlu menutup kode untuk mengirim data ke server dalam fungsi yang bertanggung jawab untuk menyiapkannya.
  • Fungsi dengan lebih dari sepuluh baris kode kemungkinan besar merupakan fungsi yang buruk.
  • Logika dan presentasi tidak boleh berjalan bersamaan.

QUnit - genre klasik dari pencipta jQuery

QUnit sangat populer di kalangan pengembang JavaScript. Pertama, didokumentasikan dengan baik dan mudah digunakan, dan kedua, dibuat oleh penulis jQuery. Pustaka ini cocok untuk menguji kode JavaScript berbasis jQuery dan asli.


Unduh versi terbaru QUnit Anda dapat dari situs resmi . Pustaka hadir sebagai file JS dan CSS tunggal. Misalkan Anda telah menemukan cara memuat komponen yang diperlukan, dan jika demikian, inilah saatnya untuk menulis uji coba. Mari kita tidak pergi jauh dan mencoba untuk menguji fungsi trim().

Untuk mendemonstrasikan pengujian, saya membuat proyek sederhana dengan struktur berikut:

  • index.html - file utama yang akan menampilkan hasil pengujian;
  • qunit-1.12.0.js - file perpustakaan QUnit;
  • example.js - file yang berisi kode untuk pengujian (dalam kasus kami, deskripsi fungsi trim());
  • test.js - file dengan tes;
  • qunit-1.12.0.css - gaya untuk mendesain laporan dengan pengujian.

Konten file index.html dan test.js ditampilkan di Listing 1 dan 2. Listing kedua yang paling menarik bagi kami adalah deklarasi fungsi yang sedang diuji (trim()) dan kode pengujian untuk memverifikasi bahwa fungsi tersebut berfungsi . Harap perhatikan bahwa fungsi trim() itu sendiri dapat ditemukan di mana saja, saya taruh di daftar kedua hanya untuk menghemat ruang di log.
Sekarang mari kita lihat tesnya sendiri. Pustaka QUnit.js menawarkan sejumlah metode:

  • test() - pembungkus untuk deskripsi tes;
  • ok() - pernyataan memungkinkan Anda untuk memeriksa kebenaran parameter pertama. Dalam contoh kita, saya memberikan panggilan ke fungsi trim() yang kita definisikan dan membandingkannya dengan nilai yang diharapkan akan saya terima. Jika kondisi benar, tes lulus;
  • equal() - metode ini memungkinkan Anda untuk memeriksa kesetaraan parameter pertama dan kedua. Perhatikan segera itu metode ini melakukan pemeriksaan non-ketat, sehingga hanya cocok untuk skalar;
  • notEqual() adalah kebalikan dari sama(). Dieksekusi jika nilai pertama tidak sama dengan nilai kedua;
  • strictEqual() - mirip dengan equal() dengan satu perbedaan - menggunakan pemeriksaan ketat (yaitu, juga memeriksa tipe data);
  • notStrictEqual() - kebalikan dari strictEqual();
  • deepEqual() - metode untuk pernyataan rekursif, digunakan untuk primitif, array, objek;
  • notDeepEqual() - kebalikan dari deepEqual();
  • raises() adalah pernyataan untuk menguji fungsi callback yang memberikan pengecualian.

Dalam daftar kedua, saya dengan jelas menunjukkan cara menerapkan metode ini dalam praktik. Jika Anda menjalankan test case dalam formulir ini, maka semua tes akan berhasil dilalui (lihat gambar yang sesuai). Untuk melihat perbedaan antara lulus ujian dan gagal ujian, saya sedikit mengubah kode satu ujian. Saya sengaja menambahkan hasil yang salah ke baris dengan pengujian menggunakan strictEqual() (lihat gambar yang sesuai).

Listing 1. Isi file index.html Menguji dengan QUnit



Dengan pengujian fungsi-fungsi sederhana tampaknya dipahami. Bagaimanapun, saya tidak punya apa-apa lagi untuk ditambahkan. Maka Anda perlu mengambil kode asli dan mencoba menulis tes sendiri. Mari kita lihat tugas lain yang sering dihadapi pengembang JavaScript - menguji fungsi asinkron. Aplikasi yang diisi dengan kode JavaScript berinteraksi 99% dengan sisi server menggunakan AJAX. Juga tidak mungkin meninggalkan kode ini tanpa pengujian, tetapi menulis tes akan terlihat sedikit berbeda. Pertimbangkan sebuah contoh:

AsyncTest("myAsyncFunc()", function () ( setTimeout(function () ( ok(myAsyncFunc() == true, "Data berhasil diteruskan"); start(); ), 500); ));

Perbedaan utama antara contoh ini dan yang sebelumnya adalah bahwa asyncTest() digunakan alih-alih pembungkus test(), sehingga secara langsung menyatakan bahwa saya tertarik dengan pengujian asinkron. Selanjutnya, saya memulai batas waktu 500 milidetik. Selama waktu ini, fungsi myAsyncFunc() harus mentransfer data ke server pengujian dan, jika semuanya baik-baik saja, mengembalikan nilai true. Inilah momen paling menarik. Saat asyncTest() dipanggil, utas eksekusi dihentikan, dan saat pengujian selesai, itu harus dimulai dengan sendirinya. Untuk mengontrol aliran eksekusi, QUnit menyediakan metode start() dan stop().


Menguji fungsi asinkron dengan pustaka QUnit cukup mudah. Contoh terakhir yang ingin saya lihat adalah menulis tes yang melakukan beberapa pemeriksaan asinkron. Pertanyaan utama yang muncul dalam tugas tersebut adalah tempat optimal untuk memulai utas eksekusi. Dokumen resmi menyarankan untuk menggunakan sesuatu seperti

AsyncTest("myAsyncFunc()", function () ( expect(3); // Lakukan tiga tes di sini ok(myAsyncFunc(), "Membuat dunia lebih baik 1"); ok(myAsyncFunc(), "Membuat dunia lebih baik 2 ") ; ok(myAsyncFunc(), "Membuat dunia menjadi tempat yang lebih baik 3"); setTimeout(function () ( start(); ), 3000); ));

Tes untuk tindakan kustom

Anda harus selalu ingat bahwa banyak hal antarmuka ditulis dalam JavaScript. Misalnya, pengguna mengklik mucikari dan sesuatu akan terjadi sebagai tanggapan atas kliknya. Ada sejumlah besar kode "antarmuka" seperti itu dalam proyek, dan itu juga perlu ditutup dengan pengujian. Mari kita lihat bagaimana kita dapat mensimulasikan penekanan tombol pengguna dan menulis pengujian terpisah untuk tindakan ini. Bayangkan kita memiliki beberapa fungsi yang mencatat tombol yang ditekan. Saya memberinya kode di daftar ketiga.

Listing 3. Mencatat fungsi penekanan tombol KeyLogger(target) ( if (!(this instanceof KeyLogger)) ( return new KeyLogger(target); ) this.target = target; this.log = ; var self = this; this.target.off ("keydown").on("keydown", function(event) ( self.log.push(event.keyCode); )); )

Sekarang mari kita coba fungsi ini untuk menguji. Pertama-tama, di badan pengujian, kita perlu meniru tombol yang ditekan. Cara termudah untuk melakukannya adalah dengan pustaka jQuery, yang memungkinkan Anda membuat acara dalam beberapa baris kode (lihat Listing 4).

Listing 4. Kode tes untuk KeyLogger test("Key recording test", function () ( var event, $doc = $(document), keys = KeyLogger($doc); event = $.Event("keydown"); event .keyCode = 9; $doc.trigger(event); sama(keys.log.length, 1, "Key dicatat"); sama(keys.log, 9, "Key ditekan dengan kode 9 dicatat"); ));

Di awal daftar dengan pengujian, saya menyiapkan acara untuk meniru penekanan tombol - "keydown". Kami akan tertarik untuk menekan tombol Tab (kode 9). Kemudian, dengan menggunakan metode trigger(), saya mengirimkan acara yang telah disiapkan, setelah itu saya dapat memulai pengujian. Pertama, kami memeriksa gambaran besarnya - apakah tombol ditekan, lalu kodenya.

DOM dengan kedok tes

Karena Qunit.js memungkinkan Anda untuk menguji tindakan kustom, menulis tes untuk DOM juga tidak akan menjadi masalah. Ini benar, dan contoh di bawah ini akan mengkonfirmasi kata-kata saya. Saya tidak akan mengomentarinya, lihat saja kodenya dan semuanya akan menjadi jelas:

Test("Menambahkan elemen div baru", function () ( var $fixture = $("#qunit-fixture"); $fixture.append("

Ini adalah div baru
"); sama($("div", $fixture).length, 1, "Div baru berhasil ditambahkan!"); ));

PhantomJS - jalankan tes dari konsol


Menulis pengujian menggunakan pustaka QUnit.js nyaman dan sederhana, tetapi cepat atau lambat Anda akan dikunjungi oleh keinginan untuk mengotomatiskan peluncuran, pengujian, dan pengumpulan hasil. Misalnya, saya memiliki mesin virtual terpisah di DigitalOcean untuk bisnis ini, yang hanya dapat saya kelola menggunakan konsol.

Proyek PhantomJS memecahkan masalah ini dengan cukup elegan. Ini bukan hanya kerangka kerja lain untuk menulis pengujian unit, tetapi versi konsol lengkap dari mesin WebKit. Sederhananya, aplikasi ini mengemulasi browser. Dengan bantuan PhantomJS, ini benar-benar tidak hanya untuk mengotomatiskan verifikasi pelaksanaan pengujian, tetapi juga untuk menyelesaikan banyak tugas yang cepat atau lambat muncul di hadapan pengembang: mendapatkan hasil rendering halaman ke file (PNG, JPG), fungsi monitor jaringan (kecepatan muat, kinerja keseluruhan, dll.), emulasi tindakan pengguna, dan sebagainya. Saya sarankan untuk tidak malas dan membaca dokumentasi resmi proyek ini, Anda pasti akan menemukan sesuatu yang menarik untuk diri Anda sendiri.

PhantomJS dapat dikompilasi untuk berbagai platform (*nix, OS X, Windows). Jika Anda mengembangkan semuanya di bawah Windows, maka tidak ada masalah - gabungkan binari, dan lanjutkan. Kesulitan kecil dalam peluncuran mungkin muncul jika Anda memasang dua adaptor video, salah satunya adalah NVIDIA. Dalam hal ini, Anda harus menggunakan retasan yang dijelaskan di bilah sisi.


Mari kita coba berkenalan dengan PhantomJS dalam praktiknya. Untuk menjalankan tes yang disiapkan di bagian terakhir melalui PhantomJS dan mendapatkan hasil eksekusi di konsol, kita memerlukan skrip loader khusus - run-qunit.js . Buka konsol (saya bekerja di Windows, jadi saya menggunakan cmd) dan ketik perintah dalam format

phantom.exe<путь к run-qunit.js> <путь к странице с тестами>

Dalam kasus saya, perintah peluncuran ternyata seperti ini:

E:\soft\phantomjs>phantomjs.exe E:\temp\testjsforx\qunit\run-qunit.js file:///E: /temp/testjsforx/qunit/index.html

Hasil eksekusinya:

Pengujian selesai dalam 2592 milidetik. 9 pernyataan dari 9 lulus, 0 gagal.

Semua tes lulus

Sangatlah penting untuk menutupi kode dengan pengujian, dan tidak masalah skala apa pun yang Anda buat untuk aplikasi tersebut. Sekali lagi, saya mengingatkan Anda: bahkan program terkecil pun berubah menjadi monster kikuk yang perlu didukung dan dilengkapi dengan fungsionalitas. Kode yang teruji dengan baik adalah kunci kesuksesan dan kualitas. Ya, tidak mudah untuk segera mulai menulis kode yang cocok untuk pengujian otomatis, tetapi percayalah, semua siksaan ini akan terbayar di masa mendatang. Itu saja untuk hari ini, semoga berhasil!

Masalah PhantomJS di Windows

Itu terjadi begitu saja, tetapi saya menguji semua contoh untuk artikel ini bukan di Linux, tetapi di bawah Windows 7 lama yang bagus. Ternyata PhantomJS memiliki beberapa masalah saat bekerja pada sistem yang menggunakan beberapa adapter video. Di laptop saya, selain chip video terintegrasi, NVIDIA juga hang out, dan karena itu PhantomJS dengan tegas menolak untuk menanggapi perintah phantom.exit (). Akibatnya, setelah skrip dieksekusi, proses PhantomJS tidak berhenti bekerja dan terus bertahan di memori. Jendela terminal juga berhenti merespons perintah keluar ( tidak membantu).

Jika Anda menghadapi masalah serupa dan berencana menggunakan PhantomJS di Windows, bersiaplah untuk melakukan peretasan berikut. panel terbuka kontrol NVIDIA. Temukan item "Pengaturan 3D" di pohon. Di sisi kanan, opsi "Preferred adaptor grafis". Secara default. nilainya diatur ke Autoselect. Kita perlu mengubahnya menjadi "Prosesor NVIDIA Kinerja Tinggi" atau "Perangkat Keras Grafis Terintegrasi". Setelah trik sederhana ini, PhantomJS mulai berperilaku patuh.

Membuat kasus uji yang efektif dapat menjadi sangat penting proyek-proyek besar, jika perilaku bagian aplikasi dapat berubah karena berbagai alasan. Mungkin masalah yang paling umum adalah ketika sekelompok besar pengembang mengerjakan modul yang sama atau terkait. Ini dapat menyebabkan perubahan perilaku fungsi yang tidak direncanakan yang ditulis oleh programmer lain. Atau bekerja di bawah tenggat waktu yang ketat menyebabkan perubahan yang tidak disengaja di bagian penting aplikasi.

Pengujian aplikasi web biasanya terdiri dari penilaian visual elemen halaman dan penilaian empiris kinerja fungsionalitas. Dengan kata lain, dalam menavigasi bagian dan melakukan tindakan pada elemen dinamis.

Seiring waktu, proyek diisi dengan yang baru Kegunaan, yang memperpanjang dan mempersulit proses pemeriksaan pekerjaannya. Pengujian unit digunakan untuk otomatisasi.

Ada 2 pendekatan untuk membangun skenario pengujian:

  • kotak putihpengujian– tes menulis didasarkan pada implementasi fungsionalitas. Itu. kami memeriksa algoritme yang sama yang menjadi dasar kerja modul sistem kami. Pendekatan ini tidak menjamin pengoperasian sistem yang benar secara keseluruhan.
  • kotak hitampengujian– scripting didasarkan pada spesifikasi dan persyaratan sistem. Dengan cara ini Anda dapat memeriksa kebenaran hasil dari seluruh aplikasi, tetapi pendekatan ini tidak memungkinkan Anda menangkap kesalahan kecil dan langka.

Apa yang harus diuji

Sepertinya ide yang bagus untuk menguji setiap fitur yang Anda terapkan. Ini tidak sepenuhnya benar. Tes penulisan membutuhkan waktu pengembang, jadi untuk mengoptimalkan proses pembuatan aplikasi, ada baiknya menyiapkan tes hanya untuk fungsi yang kompleks, kritis, atau fungsi yang bergantung pada hasil modul sistem lainnya. Tutupi tes dengan logika ambigu yang berpotensi mengandung kesalahan. Penting juga untuk membuat pengujian untuk bagian-bagian kode yang direncanakan untuk dioptimalkan di masa mendatang, sehingga setelah proses pengoptimalan Anda dapat memastikan bahwa kode tersebut dijalankan dengan benar.

Secara umum, sangat penting untuk mengevaluasi biaya pengujian terhadap ketatnya waktu pengembangan. Tentu saja, jika Anda tidak dibatasi waktu, Anda dapat membiarkan setiap fungsi ditutup dengan pengujian. Namun biasanya, pengembangan dilakukan dalam tekanan waktu yang ketat, sehingga tugas seorang analis atau pengembang berpengalaman adalah memahami di mana pengujian diperlukan. Selain itu, tes tertulis meningkatkan biaya proyek.

Dengan demikian, kami dapat merumuskan 3 kasus ketika penggunaan pengujian unit dibenarkan:

1) Jika tes memungkinkan untuk mengidentifikasi kesalahan lebih cepat daripada dengan pencarian biasanya.

2) Mengurangi waktu debug

3) Memungkinkan Anda menguji kode yang sering diubah.

Dari 3 komponen utama frontend (HTML, CSS, JavaScript), mungkin hanya kode JavaScript yang perlu diuji. CSS hanya divalidasi secara visual saat pengembang/penguji/pelanggan melihat GUI di berbagai browser. HTML - markup diperiksa dengan metode yang sama.

Bagaimana cara menguji

Saat merancang skenario pengujian, Anda harus dipandu oleh prinsip-prinsip berikut:

  • Tes Anda harus sesederhana mungkin. Maka kemungkinan besar bug yang Anda coba ulangi akan memengaruhi hasil penerapannya.
  • Mengurai tes modul besar. Grove untuk menemukan lokasi kesalahan yang spesifik.
  • Buat tes independen. Hasil dari satu tes tidak boleh bergantung pada hasil tes lainnya.
  • Hasil tes harus benar-benar dapat diulang dan diharapkan. Setiap kali Anda menjalankan tes lagi, hasilnya akan sama seperti terakhir kali.
  • Untuk setiap kesalahan dalam pelaksanaan aplikasi, skrip pengujian harus dibuat. Dengan cara ini Anda akan yakin bahwa bug tersebut benar-benar diperbaiki dan tidak terlihat oleh pengguna.

Bagaimana cara menguji

Ada beberapa perpustakaan untuk pengujian unit kode js. Mungkin yang paling umum adalah QUnit. Untuk melakukan pengujian unit menggunakan pustaka ini, kita perlu membuat "kotak pasir" - halaman html sederhana tempat pustaka pengujian akan dihubungkan, kode yang akan diuji, dan pengujian itu sendiri.

Fungsi untuk tes:

(fungsi() ( window.stepen = fungsi(int) ( var hasil = 2; untuk (var i = 1; i< int; i ++) { result = result * 2; } return result; } window.returnFunc = function() { return "ok"; } })();

Daftar tes:

Test("stepen()", function() ( sama(stepen(2), 4, "2^2 - metode yang sama"); ok(stepen(3) === 8, "2^3 - metode ok" ); deepEqual(stepen(5), 32, "2^5 - metode deepEqual"); )); asyncTest("returnFunc()", function() ( setTimeout(function() ( sama(returnFunc(), "ok", "Async Func Test"); start(); ), 1000); ));

Seperti yang Anda lihat, QUnit mendukung 3 fungsi untuk membandingkan hasil eksekusi kode dengan yang diharapkan:

  • Oke()- menganggap tes berhasil jika hasil pengembalian = benar
  • setara()- membandingkan hasil dengan yang diharapkan
  • deepEqual()- membandingkan hasilnya dengan yang diharapkan, memeriksa jenisnya

Hasil eksekusi:

Seperti yang Anda lihat, pustaka QUnit menguji kode untuk beberapa browser sekaligus.

Ada sejumlah perpustakaan lain untuk pengujian unit. Namun, konsep pembuatan skrip uji di dalamnya sama, jadi setelah berurusan dengan satu skrip, tidak akan sulit bagi Anda untuk beralih ke yang lain.

Penting untuk diingat

Fitur kode js modern adalah asinkron pelaksanaannya. Pustaka untuk pengujian biasanya memiliki kemampuan untuk melakukan pengujian asinkron. Tetapi misalnya, jika Anda mencoba menguji fungsi yang, katakanlah, mengirimkan permintaan get ke backend dan mengembalikan respons darinya, maka untuk melakukan pengujian, Anda harus menghentikan utas dengan fungsi stop(), mulai fungsi yang sedang diuji, lalu mulai ulang utas dengan metode start() , "membungkusnya" di setTimeout(). Itu. Anda harus menetapkan beberapa interval waktu di mana pelaksanaan fungsi harus diselesaikan. Seseorang harus hati-hati memilih durasi segmen ini, .k. di satu sisi, kerja panjang dari metode ini dapat berupa fitur atau bahkan kebutuhan untuk implementasi spesifik dari fungsionalitas aplikasi, atau perilaku yang salah.

Menguji Aplikasi Backbone

Untuk contoh pengujian aplikasi yang ditulis menggunakan Backbone.js, kami akan menggunakan proyek yang dijelaskan di .

Anda dapat memeriksa dengan unit test:

  • Kebenaran pembuatan model dan pengontrol
  • Kebenaran data dalam model
  • Eksekusi metode pengontrol (untuk ini mereka harus mengembalikan hasilnya)
  • Lihat keberhasilan pemuatan

Kode uji:

Test("Backbone.js", function() ( ok(sample, "Namespace check"); ok(sample.routers.app, "Router check"); ok(sample.core.pageManager.open("chat") , "Tes pembukaan halaman (Pemanggilan metode pengontrol)") ok(sample.core.state, "Model check"); equal(sample.core.state.get("content"), "sintel", "Model data get test "); stop(); ok(function() ( $.ajax(( url: "app/templates/about.tpl", tipe data: "teks" )).done(fungsi(data) ( self.$el. html(data); return data; )) ), "Pemeriksaan pemuatan template"); setTimeout(function() ( start(); ), 1000); ));

Hasil bekerja dengan kesalahan pengujian:

Otomatisasi uji coba

Biasanya, menerapkan aplikasi adalah tugas yang perlu dilakukan cukup sering selama pengembangan intensif. Oleh karena itu, operasi ini biasanya otomatis. Kami menggunakan Jenkins, alat integrasi berkelanjutan, dalam pekerjaan kami. Idenya adalah menggabungkan penerapan melalui Jenkins dengan pengujian otomatis.

Tes QUnit berjalan di browser. Phantomjs, perangkat lunak yang mengemulasi browser, akan membantu kita menyiasati fitur ini. Pengembang phantomjs telah menyediakan skrip untuk menjalankan tes QUnit, tetapi harus sedikit dimodifikasi agar berfungsi dengan benar.

/** * Tunggu hingga kondisi pengujian benar atau terjadi batas waktu. * Berguna untuk menunggu * pada respons server atau agar perubahan ui (fadeIn, dll.) terjadi. * * kondisi javascript @param testFx yang mengevaluasi ke boolean, * dapat diteruskan sebagai string (misalnya: "1 == 1" atau * "$("#bar").is(":visible")" atau * sebagai fungsi panggilan balik * @param onReady apa yang harus dilakukan ketika kondisi testFx terpenuhi, * dapat diteruskan sebagai string (mis.: "1 == 1" atau * "$("#bar").is (":visible")" atau * sebagai fungsi callback. * @param timeOutMillis jumlah maksimal waktu untuk menunggu. Jika tidak * ditentukan, 3 detik digunakan. */ function waitFor(testFx, onReady, timeOutMillis) ( var maxtimeOutMillis) = timeOutMillis - timeOutMillis: 3001, //< Default Max Timout is 3s start = new Date().getTime(), condition = false, interval = setInterval(function() { if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { // If not time-out yet and condition not yet fulfilled condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code } else { if(!condition) { // If condition still not fulfilled // (timeout but condition is "false") console.log(""waitFor()" timeout"); phantom.exit(1); } else { // Condition fulfilled (timeout and/or condition is //"true") console.log(""waitFor()" finished in " + (new Date().getTime() - start) + "ms."); typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it"s supposed to do once the // condition is fulfilled clearInterval(interval); //< Stop this interval } } }, 100); // repeat check every 250ms }; }; if (phantom.args.length === 0 || phantom.args.length >2) console.log("Penggunaan: URL run-qunit.js"); phantom.exit(); ) var halaman = Halaman Web baru(); // Mengarahkan panggilan "console.log()" dari dalam Halaman // konteks ke konteks utama Phantom (yaitu halaman "ini") saat ini.onConsoleMessage = function(msg) ( console.log(msg); ); page.open(phantom.args, function(status)( if (status !== "berhasil") ( console.log("Tidak dapat mengakses jaringan"); phantom.exit(); ) else ( waitFor(function() ( return page.evaluate(function()( var el = document.getElementById("qunit-testresult"); if (el && el.innerText.match("selesai")) ( return true; ) return false; )); ), function()( var failedNum = page.evaluate(function()( var el = document.getElementById("qunit-testresult"); console.log(el.innerText); coba ( return document.getElementsByClassName("gagal" .innerHTML.length; ) catch (e) ( return 0; ) return 10000; )); phantom.exit((parseInt(failedNum, 10) > 0) ? 1: 0); )); ) ));

Untuk menampilkan pesan hasil di konsol, Anda perlu menambahkan fungsi logging ke skrip pengujian.

Sekarang situs ini tersedia untuk menguji pengetahuan tentang topik-topik berikut: HTML, css, JavaScript, PHP, SQL.

Setiap tes terdiri dari 10 pertanyaan tentang topik tertentu. Dalam setiap pertanyaan, saya mencoba menyentuh area penerapan bahasa tertentu yang paling beragam untuk memeriksa tingkat pengetahuan Anda selengkap mungkin.

Tentu saja semuanya tes gratis dan siapapun bisa melewatinya.

Prosedur pengetesan:

  1. Ikuti tautan " Mulai pengujian" dari tes yang sesuai.
  2. Jawab pertanyaan dengan memilih satu satunya pilihan yang benar.
  3. Setelah menyelesaikan pengujian, Anda akan melihat nilai Anda, sejumlah kesalahan, Dan analisis dari setiap pertanyaan dari tes.

Perhatian! Kembali ke pertanyaan sebelumnya tidak akan berhasil, jadi pikirkan sebelum menjawab.

Tes tersedia saat ini

  1. HTML

    • Tes total lulus: 75424 orang
    • Skor rata - rata: 2,83 dari 5 poin.

    Tes pengetahuan dasar HTML. Anda perlu tahu dasar tag HTML dan penggunaan yang tepat. Penting juga untuk memahami fitur-fitur standar XHTML 1.1.

  2. css

    • Tes total lulus: 32828 orang
    • Skor rata - rata: 3,37 dari 5 poin.

    Tes menguji pengetahuan tentang dasar-dasar css. Agar berhasil lulus ujian, Anda harus mengetahui tipe dasar penyeleksi (sintaksnya), mengetahui properti dasar dan nilainya yang mungkin, dan juga mengetahui tujuan dari elemen semu yang paling populer.

  3. JavaScript

    • Tes total lulus: 24845 orang
    • Skor rata - rata: 3,31 dari 5 poin.

    Kuis ini menguji pengetahuan Anda tentang bahasa JavaScript. Pertanyaan dari tes mencakup berbagai bidang aplikasi bahasa yang diberikan. Ada banyak pertanyaan tentang memahami nuansa "kecil". Jika tidak, Anda diharuskan mengetahui hal-hal dasar: bekerja dengan variabel, fungsi JavaScript dasar, prioritas operator, dan sebagainya.

  4. PHP

    • Tes total lulus: 33239 orang
    • Skor rata - rata: 3,03 dari 5 poin.

    Kuis ini menguji pengetahuan Anda tentang bahasa PHP. Anda diminta untuk mengetahui konstruksi PHP dasar, bekerja dengan variabel, sesi, implementasi pengalihan, dan hal-hal standar lainnya.
    Permintaan yang meyakinkan: Tes tersebut berisi banyak pertanyaan seperti: "Apa yang akan dihasilkan skrip?". Permintaan besar, jangan salin dan periksa. Jujurlah pada dirimu sendiri.

  5. SQL

    • Tes total lulus: 18014 orang
    • Skor rata - rata: 3,28 dari 5 poin.

    Tes ini menguji pengetahuan Anda tentang bahasa kueri SQL. Pertanyaan hanya mencakup pengetahuan paling dasar dari bahasa ini, tanpa pendalaman apa pun. Anda akan membutuhkan pengetahuan tentang kueri SQL paling dasar, serta penggunaannya yang kompeten.

Pada contoh aplikasi kalkulator sederhana pada Node.js. Kami akan menguji menggunakan kerangka kerja Mocha.

Apa yang seharusnya dapat dilakukan oleh aplikasi kita:

  • Tambahkan, kurangi, bagi, dan gandakan dua angka apa saja;
  • Tampilkan peringatan dan keluar jika sesuatu selain nomor dimasukkan;
  • Juga harus ada antarmuka baris perintah agar pengguna akhir dapat menggunakan aplikasi tersebut.

Yang kami butuhkan:

  • Node.js dan npm
  • Pengetahuan tentang JavaScript: sintaks dan struktur kode, tipe data, operasi matematika, dan ekspresi bersyarat.

Dengan tujuan yang telah diselesaikan, Anda dapat mulai menyiapkan lingkungan untuk pengujian dan pengembangan.

Menyiapkan lingkungan

Karena kita menggunakan Node.js, kita perlu membuat lingkungan lokal untuk file dan dependensi.

Membuat folder baru perhitungan. Pada baris perintah, ubah ke direktori ini dan buat proyek baru dengan npm init , yang akan dibuat file baru package.json untuk program kami.

Anda akan diminta untuk memasukkan nama paket, versi, deskripsi, dan informasi lain tentang paket tersebut. Anda dapat memasukkan nama calc.js dan terus menekan Memasuki untuk menetapkan nilai default. Saat Anda masuk ke test command , ketik moka - ini adalah kerangka pengujian yang akan kami gunakan:

perintah tes: moka

Setelah memasukkan semua informasi, skrip akan membuat file package.json, yang terlihat seperti ini:

( "name": "calc.js", "version": "1.0.0", "description": "Kalkulator sederhana di Node.js", "main": "index.js", "scripts": ( " test": "moka" ), "penulis": "", "lisensi": "ISC" )

Langkah terakhir dalam langkah ini adalah menginstal Mocha. Masukkan perintah berikut untuk menginstal:

npm install --save-dev moka

Setelah menerapkan perintah ini, sebuah folder akan muncul node_modules, file package-lock.json, dan dalam file package.json baris berikut akan muncul:

"devDependencies": ( "mocha": "^4.0.1" )

Buat file test.js. Kami akan menggunakan modul bawaan di Node.js menegaskan untuk memeriksa apakah benar dan benar benar. Karena itu benar, tes harus lulus:

Const menegaskan = membutuhkan ("menegaskan"); itu("harus mengembalikan benar", () => ( menegaskan.sama(benar, benar); ));

Sekarang jalankan tes dari baris perintah:

$ npm test > mocha ✓ harus mengembalikan true 1 passing (8ms)

Pengujian berjalan seperti yang diharapkan, sehingga penyiapan lingkungan selesai. Hapus dari test.js semuanya kecuali garis const assert = require("assert"); .

Kami akan menggunakan file test.js sepanjang proses pengembangan aplikasi. Buat dua file lagi: operasi.js untuk fungsi aritmatika dan validasi dan calc.js untuk aplikasi itu sendiri. Kami menggunakan begitu banyak file sehingga tidak terlalu panjang dan rumit. Berikut adalah daftar file kami saat ini:

  • calc.js;
  • node_modules;
  • operasi.js;
  • package-lock.json;
  • package.json;
  • test.js;

Mari tambahkan yang pertama tes nyata untuk aplikasi kita.

Menambahkan operasi matematika

Pertama-tama, aplikasi kita harus bisa menjumlahkan, mengurangi, membagi, dan mengalikan dua angka apa saja. Jadi, untuk setiap operasi ini, kita harus membuat fungsi tersendiri.

Mari kita mulai dengan penambahan. Kami akan menulis tes yang secara unik mendapatkan jumlah yang diharapkan dari dua angka. Pada kode di bawah ini, kita memeriksa apakah jumlah 1 dan 3 sama dengan menggunakan fungsi add() 4:

Const menegaskan = membutuhkan ("menegaskan"); itu("benar menemukan jumlah 1 dan 3", () => ( menegaskan.sama(menambahkan(1, 3), 4); ));

Setelah menjalankan pengujian dengan perintah npm test, kita akan melihat hal berikut:

> mocha 0 passing (9ms) 1 gagal 1) menemukan jumlah 1 dan 3 dengan benar: ReferenceError: add is not defined at Context.it (test.js:5:16) npm ERR! tes gagal. Lihat di atas untuk detail lebih lanjut.

Tes gagal dengan ReferenceError: add is not defined . Kami sedang menguji fungsi add(), yang belum ada, jadi hasil ini cukup diharapkan.

Mari buat fungsi add() dalam sebuah file operasi.js:

Const tambahkan = (x, y) => (+x) + (+y);

Fungsi ini mengambil dua argumen x dan y dan mengembalikan jumlahnya. Anda mungkin memperhatikan bahwa kita menulis (+x) + (+y) bukan x + y . Kami menggunakan operator unary untuk memberikan argumen ke angka, jika inputnya adalah string.

Catatan Ini menggunakan fungsi panah yang ditambahkan ES6 dan pengembalian implisit.

Karena kita menggunakan Node.js dan membagi kode menjadi beberapa file, kita perlu menggunakan module.exports untuk mengekspor kode:

Const tambahkan = (x, y) => (+x) + (+y); module.exports = ( tambah )

Di awal file test.js kami mengimpor kode dari operasi.js dengan membutuhkan() . Karena kita menggunakan fungsi melalui variabel operasi, kita perlu mengubah add() menjadi operations.add() :

Operasi const = memerlukan (""./operasi.js"); const menegaskan = membutuhkan ("menegaskan"); itu("benar menemukan jumlah 1 dan 3", () => ( menegaskan.sama(operasi.tambahkan(1, 3), 4); ));

Mari kita jalankan tes:

$ npm test > mocha ✓ menemukan dengan benar jumlah dari 1 dan 3 1 passing (8ms)

Kami sekarang memiliki fungsi yang berfungsi dan tes berhasil. Karena fungsi dari operasi lain bekerja dengan cara yang sama, menambahkan pengujian untuk pengurangan() , perkalian() , dan pembagian() menjadi mudah:

It("benar menemukan jumlah 1 dan 3", () => ( menegaskan.sama(operasi.tambahkan(1, 3), 4); )); itu("benar menemukan jumlah -1 dan -1", () => ( menegaskan.sama(operasi.tambahkan(-1, -1), -2); )); itu("benar menemukan perbedaan antara 33 dan 3", () => ( menegaskan.sama(operasi.kurangi(33, 3), 30); )); it("menemukan dengan benar hasil kali 12 dan 12", () => ( assert.equal(operations.multiply(12, 12), 144); )); it("menemukan hasil bagi 10 dan 2 dengan benar", () => ( assert.equal(operations.divide(10, 2), 5); ));

Sekarang mari buat dan ekspor semua fungsi ke test.js:

Const tambahkan = (x, y) => (+x) + (+y); const kurangi = (x, y) => (+x) - (+y); perkalian const = (x, y) => (+x) * (+y); const membagi = (x, y) => (+x) / (+y); module.exports = ( tambah, kurangi, kalikan, bagi, )

Dan jalankan tes baru:

$ npm test > moka ✓ menemukan dengan benar hasil penjumlahan 1 dan 3 ✓ menemukan dengan benar hasil penjumlahan -1 dan -1 ✓ menemukan dengan benar selisih antara 33 dan 3 ✓ menemukan dengan benar hasil kali 12 dan 12 ✓ menemukan hasil bagi 10 dengan benar dan 2 5 lewat (8ms)

Semua pengujian berhasil, jadi sekarang kami yakin bahwa fungsi utama aplikasi kami akan berfungsi dengan benar. Sekarang kita dapat melakukan beberapa validasi tambahan.

Menambahkan Validasi

Saat ini, saat pengguna memasukkan nomor dan memilih operasi yang diinginkan, semuanya berfungsi dengan baik. Namun, apa yang terjadi jika Anda mencoba mencari jumlah angka dan string? Aplikasi akan mencoba melakukan operasi, tetapi karena mengharapkan angka, aplikasi akan mengembalikan NaN .

Alih-alih mengembalikan beberapa nilai aneh, saatnya melakukan tugas kedua - membuat aplikasi menampilkan peringatan dan keluar jika argumen input bukan angka.

Pertama, Anda perlu menulis fungsi yang akan memeriksa apakah input berupa angka atau bukan. Aplikasi seharusnya hanya bekerja dengan angka, jadi kami akan menangani tiga situasi:

  1. Kedua input adalah angka.
  2. Satu input adalah angka dan yang lainnya adalah string.
  3. Kedua input adalah string.
itu("melaporkan kesalahan saat menggunakan string alih-alih angka", () => ( assert.equal(operations.validateNumbers("sammy", 5), false); )); itu("melaporkan kesalahan saat menggunakan dua string, bukan angka", () => ( assert.equal(operations.validateNumbers("sammy", "sammy"), false); )); it("sukses saat menggunakan dua angka", () => ( assert.equal(operations.validateNumbers(5, 5), true); ));

Fungsi validateNumbers() akan memvalidasi kedua parameter. Fungsi isNaN() memeriksa apakah parameternya bukan angka, dan jika tidak, mengembalikan false . Jika tidak, ia mengembalikan true , yang berarti validasi berhasil.

Const validateNumbers = (x, y) => ( if (isNaN(x) && isNaN(y)) ( return false; ) return true; )

Jangan lupa untuk menambahkan validateNumbers ke module.exports di akhir file. Sekarang Anda dapat menjalankan tes baru:

$ npm test 1) melaporkan kesalahan saat menggunakan string alih-alih angka ✓ melaporkan kesalahan saat menggunakan dua string alih-alih angka ✓ berhasil saat menggunakan dua angka 7 passing (12ms) 1 gagal 1) melaporkan kesalahan saat menggunakan string sebagai gantinya angka: AssertionError : true == false + diharapkan - aktual -true + false

Dua tes lulus, tetapi satu gagal. Tes untuk dua angka berhasil, begitu pula tes untuk dua string. Apa yang tidak bisa dikatakan tentang memeriksa input string dan angka.

Jika kita melihat kembali fungsi kita, kita dapat melihatnya keduanya parameter harus NaN agar fungsi mengembalikan false . Jika kita ingin mencapai efek yang sama ketika setidaknya salah satu parameternya adalah NaN , kita perlu mengganti && dengan || :

Const validateNumbers = (x, y) => ( if (isNaN(x) || isNaN(y)) ( return false; ) return true; )

Jika Anda menjalankan pengujian npm lagi setelah perubahan ini, maka semua pengujian akan lulus:

✓ melaporkan kesalahan saat menggunakan string alih-alih angka ✓ melaporkan kesalahan saat menggunakan dua string alih-alih angka ✓ berhasil saat menggunakan dua angka 8 passing (9ms)

Kami telah menguji semua fungsionalitas aplikasi kami. Fungsi berhasil melakukan operasi matematika dan memvalidasi input. Tahap terakhir adalah pembuatan antarmuka pengguna.

Membuat antarmuka

Kami sudah memiliki fungsi yang diperlukan, tetapi pengguna masih tidak dapat menggunakannya dengan cara apa pun. Jadi kita membutuhkan antarmuka. Untuk aplikasi kami, kami akan membuat antarmuka baris perintah.

Saat ini file calc.js harus kosong. Di sinilah aplikasi kita akan disimpan. Pertama, Anda perlu mengimpor fungsi dari operasi.js:

Operasi const = memerlukan (""./operasi.js");

Antarmuka itu sendiri akan menggunakan modul Readline CLI bawaan Node.js:

Const readline = membutuhkan ("readline");

Setelah mengimpor semua yang Anda butuhkan, Anda dapat mulai membuat aplikasi. Untuk membuat antarmuka, kami akan menggunakan readline , tersedia melalui variabel rl :

Const rl = readline.createInterface(( masukan: proses.stdin, keluaran: proses.stdout ));

Hal pertama yang harus dilihat pengguna setelah memulai program adalah pesan selamat datang dan petunjuk penggunaan. Untuk melakukan ini, kami akan menggunakan console.log() :

Console.log(` Calc.js Anda telah membuka kalkulator Node.js! Versi: 1.0.0. Penggunaan: pengguna harus memasukkan dua angka dan kemudian memilih apa yang harus dilakukan dengannya. `);

Sebelum kita masuk ke fungsi kalkulator itu sendiri, mari kita periksa apakah console.log() berfungsi sebagaimana mestinya. Kami akan membuat program mencetak pesan dan keluar. Untuk melakukannya, tambahkan panggilan ke metode rl.close() di bagian akhir.

Untuk menjalankan aplikasi, masukkan node diikuti dengan nama file:

$ node calc.js Calc.js Anda telah membuka kalkulator Node.js! Versi: 1.0.0. Penggunaan: Pengguna harus memasukkan dua angka dan kemudian memilih apa yang harus dilakukan dengannya.

Program menampilkan pesan selamat datang dan keluar. Sekarang kita perlu menambahkan input pengguna. Pengguna diminta untuk memilih dua nomor dan satu operasi. Setiap masukan akan diminta oleh metode rl.question() :

Rl.question("Masukkan angka pertama: ", (x) => ( rl.question("Masukkan angka kedua: ", (y) => ( rl.question(` Pilih salah satu dari operasi berikut: Add ( +) Kurangi (-) Perkalian (*) Pembagian (/) Pilihan Anda: `, (pilihan) => ( // lebih banyak kode akan muncul di sini rl.close(); )); )); ));

Variabel x diberi nomor pertama, y ​​nomor kedua, dan pilihan adalah operasi yang dipilih. Sekarang program kami meminta input, tetapi tidak melakukan apa pun dengan data yang diterima.

Setelah input ketiga, Anda perlu memeriksa apakah hanya nomor yang dimasukkan. Untuk melakukan ini, kita akan menggunakan fungsi validateNumbers(). Menggunakan operator NOT, kami akan memeriksa apakah angka telah dimasukkan, dan jika tidak, keluar dari program:

If (!operations.validateNumbers(x, y)) ( console.log("Hanya angka yang diperbolehkan! Harap mulai ulang program."); )

Jika semuanya sudah dimasukkan dengan benar, sekarang Anda perlu menjalankan metode operasi yang sesuai yang dibuat sebelumnya. Untuk memproses empat kemungkinan pilihan, kami akan menggunakan pernyataan switch dan menampilkan hasil operasi. Jika operasi yang tidak ada dipilih, blok default akan dijalankan, memberi tahu pengguna untuk mencoba lagi:

If (!operations.validateNumbers(x,y)) ( console.log("Hanya angka yang dapat dimasukkan! Harap mulai ulang program."); ) else ( ganti (pilihan) ( case "1": console.log(` Jumlahkan $(x) dan $(y) sama dengan $(operations.add(x, y)).`); break; case "2": console.log(`Perbedaan $(x) dan $(y) sama $( operations.subtract(x, y)).`); break; case "3": console.log(`Hasil perkalian $(x) dan $(y) sama dengan $(operations.multiply(x, y) ).`) ; break; case "4": console.log(`Private $(x) and $(y) sama dengan $(operations.divide(x, y)).`); break; default: console.log ("Harap restart program dan pilih angka antara 1 dan 4."); break; ) )

Catatan Fungsi console.log() di sini menggunakan string template yang memungkinkan ekspresi.

/** * Kalkulator Node.js sederhana yang menggunakan aplikasi kalkulator yang menggunakan * antarmuka baris perintah Readline bawaan. */ operasi const = memerlukan (""./operasi.js"); const readline = membutuhkan("readline"); // Gunakan readline untuk membuat antarmuka const rl = readline.createInterface(( input: process.stdin, output: process.stdout )); console.log(` Calc.js Anda telah membuka kalkulator Node.js! Versi: 1.0.0. Penggunaan: Pengguna harus memasukkan dua angka dan kemudian memilih apa yang harus dilakukan dengannya. `); rl.question("Masukkan angka pertama: ", (x) => ( rl.question("Masukkan angka kedua: ", (y) => ( rl.question(` Pilih salah satu dari operasi berikut: Tambah ( +) Kurangi (-) Perkalian (*) Pembagian (/) Pilihan Anda: `, (pilihan) => ( if (!operations.validateNumbers(x,y)) ( console.log("Anda hanya dapat memasukkan angka! Silakan mulai ulang program."); ) else ( ganti (pilihan) ( case "1": console.log(`Jumlah dari $(x) dan $(y) sama dengan $(operations.add(x, y)). `); break; case "2": console.log(`Perbedaan antara $(x) dan $(y) adalah $(operations.subtract(x, y)).`); break; case "3": console.log(`Hasil perkalian $( x) dan $(y) sama dengan $(operations.multiply(x, y)).`); break; case "4": console.log(`Private $(x) dan $(y) sama dengan $(operations.divide(x, y)).`); break; default: console.log("Silakan restart program dan pilih angka antara 1 dan 4."); break; ) ) rl.tutup(); )); )) ; ));

Sekarang aplikasi kita sudah siap. Mari kita periksa pekerjaannya pada akhirnya. Masukkan 999 dan 1 dan pilih operasi pengurangan:

$ node calc.js Masukkan angka pertama: 999 Masukkan angka kedua: 1 Pilihan Anda: 2 Selisih antara 999 dan 1 adalah 998.

Program berhasil menyelesaikan pekerjaannya, menampilkan hasil yang benar. Selamat, Anda telah menulis kalkulator sederhana menggunakan Node.js dan mempelajari dasar-dasar pengembangan TDD.



Memuat...
Atas