Advanced Guides

Integrasi Pengujian Parse Cloud Code untuk Developer

34min

Cara mengintegrasikan pengujian ke dalam fungsi Parse Cloud Code Anda

Pendahuluan

Ini adalah panduan yang ditulis oleh John Considine, penulis tamu kami dan pengembang utama di K-Optional. Tutorial ini mencakup cara mengatur pengujian otomatis untuk Cloud Code Back4App Anda.

Kami akan membahas secara singkat tentang memindahkan beberapa kode Parse klien Anda ke cloud, dan kemudian tentang cara mengintegrasikan proyek Anda dengan ekosistem pengujian. Anda juga dapat melihat proyek contoh secara langsung untuk versi yang berfungsi.

Tujuan

Kami berharap dapat menggabungkan aspek pengujian otomatis yang kuat dan dapat diskalakan dengan lingkungan Parse yang ramah pengembang. Dengan memanfaatkan Cloud Code, mungkin fitur Parse yang kurang dihargai, pengembang dapat terus dengan cepat mengiterasi kode mereka DAN yakin bahwa perangkat lunak akan berjalan seperti yang diharapkan.

Pengembangan Berbasis Pengujian adalah bidang yang sangat luas; daripada berbicara secara filosofis tentang pengujian, kami akan menjalankan implementasi dan membahas beberapa strategi (stubbing misalnya).

Prasyarat

Untuk menyelesaikan tutorial ini, Anda perlu:

Catatan: Perpustakaan ini akan menggunakan JavaScript Promise, yang seharusnya tidak terlalu rumit

Mari kita buat backend media sosial dasar

Document image


Oke! Bayangkan aplikasi media sosial yang mencakup model profil untuk disandingkan dengan model pengguna. Untuk beberapa aplikasi, Anda mungkin menempatkan informasi profil dalam model pengguna, meskipun dalam banyak kasus ini tidak efisien; Anda sering kali perlu memisahkan kepentingan otorisasi/otentikasi dengan konten pengguna, dan dengan demikian mempertahankan dua model yang berbeda.

Dalam tutorial ini, kita akan menerapkan fitur yang mengelola pembuatan pengguna dan profil dengan cara ini, dengan memberikan beban minimal pada klien. Mari kita mulai!

1. Mendefinisikan Fungsi Kita

Ini mengasumsikan Anda telah membuat proyek Back4App, dan alat baris perintah terinstal (lihat prasyarat).

Untuk contoh kode frontend, panduan ini akan merujuk pada sintaks SDK JavaScript Parse untuk kesederhanaan

Ketika seseorang mendaftar untuk aplikasi ini, profil harus dibuat dan dihubungkan dengan objek pengguna.

Fungsi pendaftaran

Pada banyak aplikasi Parse, Anda akan membuat pengguna dengan sintaks berikut

JS


Dalam kasus kami, kami juga ingin menginisialisasi sebuah Profil, dan mengarahkannya ke objek Pengguna.

Parse Server 3.X
Parse Server 2.X


Anda bisa memperpendek sintaks itu menjadi sesuatu seperti ini:

Parse Server 3.X
Parse Server 2.X


Sayangnya, ini masih melibatkan pembuatan dua permintaan terpisah ke Parse Server yang tidak efisien untuk dilakukan oleh frontend; adalah bijaksana untuk menghindari alur komunikasi klien-server bertahap ganda jika memungkinkan.

Juga, terkait keamanan, kode di atas menempatkan proses pembuatan di tangan klien yang tidak pernah cerdas. Kami ingin mencegah integritas data kami bergantung pada klien yang menyelesaikan semua langkah alur dengan benar. Mereka bisa, misalnya, mengirim permintaan kustom yang membuat pengguna tanpa profil, merusak data persisten aplikasi.

Mengapa tidak melakukan semua ini dalam satu langkah menggunakan kode cloud? Ini dapat mencegah pembengkakan kode frontend, dan memastikan bahwa klien tidak melakukan pekerjaan yang tidak perlu/tidak aman!

Inilah yang ingin kami lakukan sebagai gantinya dari klien untuk pendaftaran

JS


Parse juga mendefinisikan untuk beforeSave trigger, memungkinkan pembuatan profil saat pengguna mendaftar. Namun dengan menggunakan fungsi kita dapat secara intuitif melewatkan atribut firstname dan lastname yang akan digunakan profil

Fungsi pendaftaran kode cloud

Mari kita mulai! Pindah ke direktori proyek Anda yang disinkronkan dengan Back4App (lihat prasyarat jika Anda tidak tahu apa artinya). Kami akan mengasumsikan struktur berikut:

1 ./cloud 2 ./cloud/main.js

Dalam kasus kami, saat inisialisasi, kami memilih 'cloud' sebagai Nama Direktori kami. Direktori Anda dapat disebut apa pun yang Anda inginkan.

Parse Server 3.X main.js
Parse Server 2.X main.js


Anda mungkin memperhatikan opsi 'useMasterKey' yang diteruskan; ini memungkinkan kode cloud untuk mengesampingkan peran atau ACL yang mungkin ada. Karena klien tidak menyentuh kode ini, tidak ada risiko mereka mengambil alih server kami. Namun, harap berhati-hati dengan bendera ini!

Jika tidak jelas mengapa ini mungkin lebih disukai daripada menempatkan fungsionalitas ini di kode klien, berikut adalah beberapa keuntungan:

  • Memindahkan komputasi ke server daripada perangkat
  • Secara eksplisit mendefinisikan fungsionalitas dari suatu proses
  • Lebih mudah untuk membuat fungsi yang aman dari kegagalan
  • Memberikan klien antarmuka yang intuitif
  • Ini mencegah kemungkinan bahwa klien akan ‘setengah melakukan’ suatu proses.

2. Mengubah struktur direktori kami

Bagus, kami telah membuat dua fungsi cloud. Kami jelas bisa menguji fungsi-fungsi ini dengan menjalankannya dan memeriksa Parse Dashboard, tetapi itu tidak dapat diskalakan atau efisien. Sebaliknya, kami ingin membuat tes otomatis khusus untuk metode yang dapat dijalankan secara terus-menerus. Jadi kami akan memisahkan kode kami sedikit.

Kami akan memindahkan fungsi yang kami buat di main.js ke file baru bernama cloud-functions.js (di direktori yang sama). Kemudian kami akan mengimpor fungsi-fungsi ini ke dalam main, dan mengikatnya ke definisi Cloud Function. Ideanya adalah untuk memisahkan fungsi-fungsi dari antarmuka cloud sehingga kami dapat mengujinya tanpa mengirim permintaan HTTP secara tidak efisien. Ini akan sangat masuk akal saat kami membuat suite tes.

membuat file fungsi

# ingat, direktori 'cloud' ditentukan # ketika kami menginisialisasi direktori dengan proyek Back4App kami # periksa Prasyarat jika ini tidak masuk akal touch ./cloud/cloud-functions.js

Anda mungkin sudah tahu bahwa Anda dapat menggunakan ‘require’ di Node.js untuk menarik fungsi, objek, dan variabel dari file lain.

Oleh karena itu, kami akan mendefinisikan fungsi yang sesuai dengan Parse Cloud Function yang kami buat di Langkah 1.

Satu poin yang mungkin membingungkan adalah bahwa fungsi yang kami definisikan akan mengembalikan fungsi, yang kemudian dapat dihubungkan ke definisi Parse Cloud. Mungkin terasa aneh menggunakan fungsi untuk mengembalikan fungsi, tetapi ini akan memberi kami kekuatan untuk mengganti Parse Servers nanti saat kami menulis tes kami.

Anda mungkin telah memperhatikan bahwa Anda dapat menggunakan objek Parse di Cloud Code Anda, tanpa harus mendefinisikan atau mengimpornya. Ini disebabkan oleh server yang menjalankan kode ini menambahkan Parse secara otomatis. Namun, jika kami ingin menjalankan tes pada fungsi secara lokal, kami tidak memiliki instance. Sebenarnya, kami ingin menyediakan instance kami sendiri yang sesuai dengan server Parse tes, di mana tidak ada bahaya dalam data yang dibuat atau dihapus.

Jadi setiap fungsi akan menerima ‘Parse’ sebagai parameter, dan mengembalikan fungsi cloud.

Parse Server 3.X cloud-functions.js
Parse Server 2.X cloud-functions.js


Di main.js, hapus semuanya dari sebelumnya. Impor Cloud Function, dan ikat fungsi tersebut ke definisi Cloud Function seperti ini:

JS


Bagus! Kami tidak mengubah fungsionalitas sama sekali sejak langkah 1, tetapi kami telah memisahkan fungsi dari Kode Cloud. Di langkah berikutnya kami akan membuat pengujian unit!

3. Buat suite pengujian

Untuk suite pengujian kami, kami akan menggunakan Jasmine, kerangka pengujian yang populer. Namun, kode kami sejauh ini sepenuhnya netral terhadap pengujian kami, jadi Anda dapat menggunakan kerangka kerja atau platform apa pun yang Anda pilih.

Mari kita instal Jasmine dan Jasmine-node (integrasi Jasmine dan lingkungan Node.js kami)

$ npm install jasmine jasmine-node --save-dev

Sekarang mari kita instal dua pustaka yang akan digunakan oleh suite pengujian kita. Ini akan menggunakan Parse SDK untuk terhubung ke Parse Server palsu, dan pustaka events untuk menyiapkan objek permintaan

$ npm install parse events --save-dev

Sekarang, menggunakan utilitas Jasmine, mari kita inisialisasi direktori pengujian kita.

$ ./node_modules/jasmine/bin/jasmine.js init

Jika Anda mau, Anda dapat menginstal jasmine secara global dengan $ npm install -g jasmine, kemudian Anda dapat menginisialisasi dengan $ jasmine init

Panduan ini akan mengasumsikan Anda tidak menginstal Jasmine secara global, meskipun itu disarankan. Jika Anda melakukannya, Anda dapat mengganti semua instance ‘/node_modules/jasmine/bin/jasmine.js’ dengan hanya ‘jasmine’

Ini harus membuat direktori bernama spec, yang di dalamnya termasuk folder dukungan yang berisi informasi konfigurasi untuk Jasmine.

Secara default, Jasmine tahu untuk mencari file yang diakhiri dengan ekstensi “.spec.js”, jadi kita akan menamai pengujian kita sesuai.

Buat file untuk pengujian unit pertama kita:

$ # di direktori ./spec $ touch signup-user.spec.js'

Tambahkan direktori utilitas dengan dua file yang akan membantu dengan pengujian kita:

$ # di direktori ./spec $ touch utils/purge-parse-table.js $ touch utils/response-stub.js

Akhirnya, buat file konstanta di direktori yang sama. Utilitas untuk file ini akan dijelaskan nanti

$ # di direktori ./spec $ touch constants.js

Berikut adalah tampilan direktori Anda sekarang:

├── cloud │ ├── cloud-functions.js │ ├── main.js ├── node_modules ├── spec │ ├── support │ │ ├── jasmine.json │ ├── utils │ │ ├── purge-parse-table.js │ │ ├── response-stub.js │ ├── signup-user.spec.js │ ├── constants.js

4. Menukar dengan Parse Server pengujian

Pengujian di sekitar Parse

Karena metode kita melibatkan Parse Server, kita ingin dapat menguji interaksi itu. Ada dua cara untuk melakukannya:

A. Kita dapat "stub" objek Parse SDK, dengan mendefinisikan objek yang mengimplementasikan antarmuka yang sama. Kemudian cukup kirim objek itu sebagai parameter ke metode cloud kita. Itu mungkin terlihat seperti ini.

JS


B. Pendekatan lain adalah menyiapkan Parse Server yang nyata yang hanya akan melayani data uji. Ini akan melibatkan lapisan HTTP yang lambat yang digunakan Parse, tetapi juga memungkinkan kita untuk menguji data di database. Dalam pengujian kita, kita perlu mengimpor Parse SDK, dan mengkonfigurasinya dengan server uji.

Document image


Dua tempat yang dapat di-stub saat menguji kode cloud: A.) Stub Parse SDK yang tidak akan membuat permintaan HTTP, atau B.) Tukar dengan implementasi database uji

Tidak ada dari kedua pendekatan ini yang merupakan jawaban "benar". Itu tergantung pada apa yang ingin Anda uji. Meng-stub antarmuka untuk Parse SDK (bahkan hanya bagian yang kita gunakan) adalah pekerjaan yang banyak. Selain itu, kita akan menguji ketahanan data setelah disimpan dalam contoh ini, jadi kita akan menggunakan pendekatan kedua.

Mari:

  • Buat Parse Server uji di Back4App
  • Ambil Application ID, dan Master Key dan simpan ke dalam file konstanta kita
  • Inisialisasi Parse SDK di file spesifikasi kita, sehingga pengujian kita menggunakan server uji

Anda dipersilakan untuk menjalankan Parse Server lokal untuk pengujian Anda. Kita akan cukup membuat aplikasi Back4App lain di dasbor kita.

Jika Anda perlu penyegaran tentang cara menyediakan server Back4App lain, silakan kunjungi tutorial Buat Aplikasi Baru. Sebut aplikasi Anda apa pun yang Anda inginkan, meskipun mungkin bijaksana untuk menggunakan sesuatu seperti TestBackend. Kemudian ambil Application ID dan Master Key dari Dashboard > Pengaturan Aplikasi > Keamanan & Kunci.

Sekarang simpan token ini di file konstanta kita seperti ini:

JS


JANGAN masukkan ID Aplikasi dan Kunci Master dari Aplikasi Produksi Anda!!! Kami akan menghapus data, dan melakukannya akan berisiko kehilangan data

5. Utilitas Pengujian

Fungsi cloud diteruskan sebagai parameter dalam objek Permintaan dan Respons Express.

Server secara otomatis membuat parameter ini ketika dijalankan di cloud, jadi untuk lingkungan pengujian kita harus membuat ganda.

Kasus ini lebih mudah. Ketika fungsi cloud dipanggil, data diteruskan; dalam kasus kita, profil dan informasi pengguna diteruskan. Setiap argumen yang diberikan dapat diakses dari properti request.params.

Jadi jika kita memanggil fungsi cloud seperti

JS


Maka properti request.params akan berisi data yang diteruskan:

JS


Cukup sederhana, untuk pengujian kami, saat memanggil fungsi cloud kami, argumen pertama harus dalam bentuk

JS


Dengan demikian, kami tidak perlu membuat objek tiruan khusus dalam kasus ini.

Objek respons memungkinkan kode cloud untuk mengirim respons HTTP ke klien yang mewakili baik keberhasilan atau kegagalan. Kami ingin tahu apa yang disebut saat memanggil fungsi cloud. Di bawah ini adalah sebuah objek tiruan yang akan memungkinkan pengujian kami untuk menentukan apakah pemanggilan tersebut berhasil atau tidak. Jika ini membingungkan, jangan khawatir, cukup tempatkan di file ./spec/utils/response-stub.js Anda.

JS


Singkatnya, fungsi konstruktor javascript ini akan memberikan cara bagi pengujian kami untuk memasukkan objek respons yang menunjukkan melalui resolusi / penolakan Promise apakah Fungsi Cloud akan mengembalikan keberhasilan atau kesalahan.

Membersihkan basis data

Kami jelas tidak ingin basis data Parse pengujian kami menyimpan apa yang terakumulasi selama pengujian. Mari kita definisikan utilitas untuk membersihkan tabel basis data, yang dapat dipanggil sebelum (atau setelah) kasus pengujian.

Tambahkan yang berikut ke ‘spec/utils/purge-parse-table.js’:

JS


Setelah mendefinisikan fungsi ini, ini adalah waktu yang baik untuk mengingatkan Anda untuk memastikan bahwa spec/utils/constants.js Anda dikonfigurasi untuk Aplikasi Parse TEST Anda, BUKAN Aplikasi Parse Produksi Anda. Ini akan menghapus data, jadi harap konfirmasi bahwa ini adalah database kosong yang Anda buat di atas

Fungsi ini menerima SDK Parse yang telah kita konfigurasi, dan mengembalikan fungsi lain. Fungsi yang dikembalikan menerima nama tabel, dan menghapus semua data dari tabel Parse yang sesuai.

Sekali lagi, ide mengembalikan fungsi mungkin tampak aneh, tetapi ini memungkinkan spesifikasi pengujian untuk mengonfigurasi endpoint Parse, dan kemudian merujuk ke fungsi yang akan menghapus tabel endpoint Parse ITU

Keren! Sekarang mari kita tulis pengujian kita!

6. Uji bahwa Fungsi Cloud akan mengirimkan kesalahan jika parameter yang tepat tidak dikirim

Fungsi Cloud bergantung pada parameter tertentu yang disertakan dan harus gagal jika, misalnya, ‘firstname’ tidak dikirim. Mari kita pastikan.

Kita akan mengedit file pengujian kita (akhirnya!) spec/signup-user.spec.js.

Ini yang perlu dilakukan sebelum definisi tes:

  • Impor SDK NodeJS Parse
  • Impor konstanta kami, dan konfigurasikan SDK Parse untuk mengarah ke server pengujian kami
  • Impor Fungsi Cloud kami
  • Impor utilitas “Purge Table” kami
  • Impor Objek Mock Respons yang kami buat

Yang berikut akan dilakukan:

JS


Sekarang mari kita tambahkan kasus uji. Pengenalan Jasmine mungkin membantu untuk memahami struktur dengan lebih baik, tetapi terlihat seperti ini (diambil dari pengantar):

describe("Sebuah suite", () => { it("mengandung spesifikasi dengan harapan", () => { expect(true).toBe(true); }); });

Jadi blok deskripsi mengenkapsulasi suite tes, dan blok ‘it’ mewakili kasus dan harapan.

Dengan melewatkan parameter ke blok ‘it’, Anda dapat menjalankan tes secara asinkron. Tes tidak akan selesai sampai parameter dipanggil seperti ini:

it("tidak akan selesai sampai done dipanggil", (done) => { setTimeout(() => { done(); }, 100); // 100 ms expect(x).toBe(y); })

Ini berguna karena salah satu tes kami akan menggunakan HTTP, sehingga harus dijalankan secara asinkron dengan cara ini karena menggunakan HTTP adalah prosedur non-blokir di NodeJS.

Selain itu, Jasmine memungkinkan blok khusus dalam suite yang dapat dijalankan pada titik yang berbeda dalam siklus hidup pengujian. Kami ingin menghapus semua tabel sebelum setiap pengujian, jadi kami akan mengeksekusi kode pembersihan di blok beforeEach.

Cukup berbicara, mari kita tambahkan beberapa kode! Tempatkan kode di bawah ini ke dalam spec/signup-user.spec.js Anda, di bawah impor yang sudah kami tambahkan:

JS


Keren, pengujian pertama kami sudah selesai. Di blok beforeEach, kami menghapus tabel User dan Profile. Kemudian kasus pengujian pertama dipicu. Ini memverifikasi bahwa mengirimkan parameter yang tidak valid ke fungsi signupUser menyebabkan fungsi tersebut mengirimkan kesalahan.

Ini menggunakan stub respons untuk memastikan fungsi akhirnya ditolak. Karena ‘signupUser’ akan gagal, blok ‘then’ awal pada stub tidak boleh dipanggil. Jika dipanggil, maka pengujian kami gagal!

Silakan jalankan pengujian menggunakan yang berikut:

$ ./node_modules/jasmine/bin/jasmine.js spec/signup-user.spec.js

Anda seharusnya melihat output berikut:

Diacak dengan benih 24618 Dimulai .. 1 spesifikasi, 0 kegagalan Selesai dalam 1.376 detik Diacak dengan benih 24618 (jasmine --random=true --seed=24618)

7. Uji Pada Persistensi Data

Semoga Anda memiliki satu uji lagi dalam diri Anda! Kami akan memverifikasi bahwa ketika Fungsi Cloud kami berjalan dengan baik, basis data kami akan sesuai harapan: sebuah Profil akan ada, dengan referensi ke objek Pengguna, keduanya dengan atribut yang diharapkan.

Tambahkan blok berikut ke blok suite ‘describe’ yang ada:

JS


Oke ini banyak, jadi mari kita langkah demi langkah melalui apa yang terjadi.

Kami menginstansiasi objek mock respons, seperti pada kasus uji pertama. Kemudian kami menjalankan signupUser dengan double permintaan yang berisi parameter yang valid, serta mock respons (baris 6-16).

Selanjutnya, kode ini mendengarkan metode onComplete objek mock, yang akan mengembalikan sebuah Promise. Promise akan ditolak jika response.error dipanggil, dan akan diselesaikan jika response.success dipanggil. Setiap penolakan akan menyebabkan rantai Promise melompati blok catch. Oleh karena itu, metode fail ditempatkan di blok catch, karena uji harus gagal jika Promise ditolak.

Respons dari Promise seharusnya menyelesaikan ke objek profil. Setelah diselesaikan, kami akan melakukan kueri untuk profil dengan nama belakang yang sama seperti yang kami buat (baris 19-21). Kemudian uji mengonfirmasi bahwa ‘firstname’ dari profil adalah yang sama dengan yang kami berikan (baris 25-26).

Blok berikutnya mengambil objek pengguna yang terkait dengan profil. Pointer objek Parse mengambil secara terpisah, oleh karena itu diperlukan blok Promise lain.

Akhirnya, kode mengonfirmasi bahwa pengguna yang sesuai memiliki nama pengguna yang diberikan ke fungsi signupUser. Kemudian uji selesai.

Silakan jalankan suite sekali lagi: Silakan jalankan tes menggunakan yang berikut:

$ ./node_modules/jasmine/bin/jasmine.js spec/signup-user.spec.js

Anda seharusnya melihat output berikut:

Acak dengan seed 24618 Dimulai .. 2 spesifikasi, 0 kegagalan Selesai dalam 2.876 detik Acak dengan seed 24618 (jasmine --random=true --seed=24618)

Keren! kami telah menulis beberapa kode cloud, dan mengintegrasikan kerangka pengujian.

Kesimpulan

Jika Anda tersesat, atau hanya ingin kode untuk contoh ini, silakan kunjungi Repo GitHub. Ikuti instruksi untuk mengunduh dan menjalankannya.

Jika ada yang tidak jelas, atau tidak berfungsi, silakan hubungi saya melalui Gmail saya, jackconsidine3.

Saya harap Anda menikmati tutorial ini, dan mendapatkan beberapa wawasan!