TypeScript Semua Hal dalam Tes Cypress Anda #frontend@twiliosendgrid

Diterbitkan: 2020-11-14

Di Twilio SendGrid, kami menulis sebagian besar aplikasi web frontend kami, terutama halaman dan fitur baru, dengan TypeScript dan React hari ini untuk pengecekan tipe, pemeliharaan, dan dokumentasi basis kode kami yang lebih baik. Ketika kami pertama kali mulai menulis pengujian Cypress lebih dari dua tahun yang lalu, sebagian besar objek halaman, pembantu, dan file spesifikasi kami masih diimplementasikan dalam JavaScript dan kami sebagian besar telah menggunakan Cypress versi 3.xx Pengujian yang lebih baru sudah ditulis dalam TypeScript tetapi kami masih memiliki banyak file untuk dikonversi dan dipindahkan ke TypeScript.

Kami ingin memetik manfaat dari mengetikkan komponen, pengujian unit, dan pengujian Cypress E2E kami sepenuhnya . Apa yang membuat prosesnya lebih mudah adalah migrasi ke versi Cypress yang lebih baru untuk memanfaatkan dukungan TypeScript sejak Cypress 4.4.0.

Jika Anda ingin mundur selangkah dan mempelajari lebih umum cara berpikir tentang menulis tes E2E, silakan lihat posting blog ini. Jika Anda juga ingin melihat ikhtisar seribu kaki tentang hal-hal paling umum yang telah kami gunakan atau lakukan sebelumnya dengan menulis tes Cypress di lingkungan yang berbeda, Anda dapat merujuk ke posting blog ini sebelum mulai menambahkan TypeScript ke tes Cypress Anda. Posting blog ini mengasumsikan Anda sudah familiar dengan tes Cypress dan telah menggunakan API mereka sebelumnya.

Jika Anda siap untuk melihat bagaimana kami mengetik, pertama-tama mari kita lihat beberapa perubahan awal seperti menambahkan dukungan TypeScript ke Cypress jika Anda berasal dari versi yang lebih lama.

Migrasi dari Cypress 3.x ke >= 4.4.0

Bagi mereka yang telah mengonfigurasi infrastruktur Cypress mereka untuk bekerja dengan TypeScript di Cypress versi 3.xx hingga 4.4.3, kemungkinan besar Anda mengalami beberapa percobaan dan kesalahan dalam menyiapkan konfigurasi praprosesor Webpack yang tepat di plugins/index.js Anda. Untuk tim Twilio SendGrid, ada beberapa gotcha dengan file tertentu yang memerlukan file JavaScript di plugins dan folder support dan kesalahan Cypress yang sulit di-debug akan muncul. Setelah Anda mendapatkan sesuatu yang berfungsi, itu akan terlihat seperti ini.


Setelah memutakhirkan dari versi 3.xx sebelumnya, kami dapat menghapus konfigurasi praprosesor Webpack kami, mengganti file plugins/index.js kami dengan file index.ts , sedikit mengotak-atik tsconfig.json folder Cypress kami, dan akhirnya, menggunakan file TS di folder Cypress kami (seperti some_page.spec.ts , index.d.ts , atau page_object.ts )–tidak ada lagi konfigurasi praprosesor Webpack dan itu berhasil! Kami senang dengan betapa jauh lebih bersih dan lebih baik untuk tidak mengelola konfigurasi praprosesor Webpack Anda sendiri dan memiliki cakupan TypeScript yang lebih baik atas file kami seperti yang ditunjukkan di bawah ini.

Dengan dukungan TypeScript yang tercakup, kami kemudian melihat contoh aplikasi dunia nyata tim Cypress, repo aplikasi dunia nyata cypress, untuk mempelajari lebih lanjut tentang cara mengetik sesuatu dengan lebih baik. Kami menemukan cara mengetik cy.task(“pluginName”, { … }) dan Cypress.env(“someEnvVar”) untuk rantai yang lebih baik dan ketik dukungan intellisense saat memperbarui file. Kami juga menggali dokumentasi TypeScript yang menyertainya. Ini mengajari kami cara mengetik hal-hal seperti perintah khusus cy.login() kami dan cara menyiapkan file konfigurasi tsconfig.json . Aplikasi contoh juga memiliki tsconfig.json untuk Anda referensi, yang dapat memberi Anda konfigurasi TypeScript dasar yang bagus untuk Anda sesuaikan dengan preferensi Anda. Kami menyarankan Anda untuk tetap up to date dengan versi Cypress terbaru, menyelami sumber daya Cypress resmi, dan bereksperimen dengan file definisi tipe Anda.

Mengetik Perintah Kustom

Kami membuat beberapa perintah kustom global seperti cy.login() untuk menangani login melalui API sehingga dapat digunakan kembali di semua file spesifikasi kami. Berikut adalah contoh bagaimana Anda dapat mengetikkan perintah kustom login Anda sendiri yang diberikan kredensial pengguna dan mengembalikan token autentikasi.

Mengetik Variabel Lingkungan

Untuk menangani beberapa lingkungan pengujian seperti dev dan staging, kami memanfaatkan konfigurasi variabel lingkungan seperti: "testEnv" untuk menampung lingkungan mana yang sedang kami uji seperti staging, "apiHost" untuk menampung host API backend, dan lainnya variabel. Anda dapat mengetikkan panggilan Cypress.env() Anda untuk mengetik lebih baik fungsi dan objek lain yang mengandalkan penggunaan nilai variabel lingkungan seperti ini.

Mengetik Plugin

Kami membuat banyak fungsi plugin cy.task() untuk menangani berbagai hal dari panggilan API, polling untuk layanan, dan memeriksa email yang cocok di kotak masuk email pengujian. Sebelumnya ketika merantai salah satu panggilan fungsi ini seperti cy.task().then((data) => {}) , subjek data yang dirantai akan diketik sebagai any atau unknown , yang tidak bagus untuk file TypeScript kami. Kami menemukan melalui contoh Cypress cara mengetik plugin dengan lebih baik berdasarkan nama plugin dan argumen yang diteruskan dalam panggilan fungsi. Ini memungkinkan file TypeScript kami untuk mendeteksi tipe data yang dirantai.

Satu masalah kecil yang kami alami adalah bahwa nama plugin dan argumen harus sama persis dengan cara Anda mengetiknya. Kami menemukan bahwa penting untuk mengarahkan kursor ke tipe .then( .then() yang dirantai dan objek argumen cy.task() di editor Anda untuk menggandakan periksa jenis yang cocok dengan benar. Terkadang, jika Anda menggunakan subjek yang dirantai dari fungsi Cypress lain seperti cy.getCookie(“auth_token”).its(“value”).then((token) => { }) atau cy.wrap(data).then((data) => {}) , Anda juga perlu mengetikkan argumen data berantai tersebut sebelum meneruskannya sebagai argumen fungsi cy.task(..., { token, data }) atau Anda masih akan melihat cy.task(...).then((data) => { }) bagian data diketik sebagai any atau unknown . Sebaiknya Anda lebih eksplisit dalam banyak tipe fungsi Cypress yang dirantai seperti .its(“value”).then((token: string) => {}) atau cy.wrap(data).then((data: DataType) => {}) sebelum meneruskannya sebagai bagian dari objek argumen cy.task() untuk memastikan tipenya berfungsi kembali.

Kami membuat file plugin Typescript terpisah yang akan mengekspor fungsi untuk digunakan kembali di plugins/index.ts kami. Seiring bertambahnya jumlah plugin, kami menyarankan Anda untuk mengatur implementasi fungsi plugin ini berdasarkan halaman atau fitur untuk menjaga file plugins/index.ts Anda tetap kecil. Anda harus membuatnya lebih mudah untuk membaca sekilas di mana Anda mendefinisikan semua fungsi cy.task(...) Anda di file plugins/index.ts Anda. Anda akhirnya dapat mengetikkan fungsi tugas ini di index.d.ts Anda dengan cara berikut:

Menyatukan semuanya dalam file deklarasi tipe

Kami menempatkan semua tipe kami untuk perintah kustom, variabel lingkungan, dan plugin kami dalam file index.d.ts di folder support . Kami menyarankan Anda untuk menempatkan semua jenis Cypress Anda juga dalam file definisi TypeScript utama untuk menjaga semuanya tetap teratur. Untuk melewati tipe yang hilang dalam dependensi eksternal yang digunakan dalam kode pengujian Cypress, Anda juga dapat mendefinisikan file modul seperti “some-lib.d.ts”, yang akan menyertakan declare module 'some-lib' , untuk mengatasi peringatan TypeScript library. Anda bahkan dapat menggunakan fitur tipe impor TypeScript untuk memasukkan tipe/antarmuka yang ditentukan di dalam file plugin/utils Anda yang lain untuk menghindari duplikasi definisi tipe Anda dalam banyak file. Anda dapat menambahkan jenis ini dalam ruang nama Cypress dan mengaturnya dengan cara berikut:

Mengetik objek perlengkapan uji, objek halaman, dan file spesifikasi

Saat kami ingin memuat berbagai pengguna dan metadata untuk lingkungan pengujian, kami sebelumnya menggambarkan bagaimana kami dapat menggabungkan variabel lingkungan seperti "testEnv" dengan nilai "pengujian" atau "pementasan" untuk mengekstrak "pengujian" atau " pementasan" objek dari objek perlengkapan uji keseluruhan. Anda dapat mengetik objek lingkungan perlengkapan uji ini dengan generik untuk struktur yang konsisten untuk semua spesifikasi Anda untuk dibagikan. Untuk setiap lingkungan pengujian, Anda dapat memiliki kredensial pengguna dan bidang meta yang sama menggunakan tipe generik untuk pengujian guna menambahkan properti sebanyak yang diperlukan. Lihat contoh di bawah ini.

Mengetik objek halaman dan mengetik file spesifikasi yang sesuai bergantung pada perintah Cypress, plugin, dan utilitas lain yang Anda gunakan. Untuk sebagian besar, mengetik objek halaman atau file spesifikasi tidak memerlukan banyak perubahan dari rekan JavaScript mereka (dengan asumsi Anda sudah mengetikkan plugin dan panggilan variabel lingkungan). Terkadang, fungsi pembantu objek halaman yang Anda tetapkan mungkin memerlukan beberapa argumen untuk diketik atau respons yang kembali dari panggilan cy.request() mungkin perlu diketik dengan as response.body as SomeType . Secara keseluruhan, editor Anda seperti VSCode dapat secara otomatis mendeteksi jenis berantai dari cy.task() atau cy.customCommand() Anda tanpa Anda perlu menambahkan lebih banyak jenis dalam file spesifikasi Anda untuk mengimbangi peringatan TypeScript apa pun.

Berikut adalah contoh bagian dari objek halaman dengan beberapa fungsi pembantu dan file spesifikasi yang menggunakan objek halaman, perintah kustom masuk, dan tugas plugin.

Kesimpulan

Menambahkan TypeScript ke pengujian Cypress kami membantu kami menghindari bug dan meningkatkan pengalaman pengembang kami saat menulis pengujian Cypress. Saat menggunakan cy.task() , Cypress.env() , dan cy.customCommand() , kita bisa mendapatkan pemeriksaan tipe yang lebih baik pada argumen fungsi dan output serta memanfaatkan penyelesaian kode di IDE kita seperti VSCode.

Kuncinya adalah membuat file deklarasi tipe Anda sendiri seperti file index.d.ts di mana Anda dapat mengganti atau memperluas antarmuka "Cypress" dan "Chainable" berdasarkan perintah khusus, variabel lingkungan, dan fungsi plugin tugas Anda menggunakan. Di objek halaman Anda dan file TypeScript spesifikasi, Anda kemudian dapat menggunakan fungsi Cypress tersebut dan mengarahkan kursor ke atau mengikuti definisi tipe input dan output yang diharapkan.

Selain itu, coba gunakan TypeScript dengan Cypress karena telah mendukung TypeScript di versi yang lebih baru. Uji apakah ini membantu Anda mendokumentasikan fungsi dengan lebih jelas dan menghindari penggunaan API yang salah. Pengujian TypeScript Anda kemungkinan akan tetap terlihat mirip dengan pengujian JavaScript Cypress Anda, sehingga Anda dapat terus mengonversi beberapa pengujian sekaligus untuk membandingkan dan membedakan pendekatannya.

Jika Anda tertarik dengan lebih banyak posting terkait dengan apa yang kami pelajari dari pengujian Cypress kami, berikut adalah beberapa artikel yang harus Anda baca:

  • Apa yang Harus Dipertimbangkan Saat Menulis Tes E2E
  • 1.000 Kaki Ikhtisar Menulis Tes Cypress
  • Berurusan Dengan Arus Email dalam Tes Cypress
  • Ide untuk Mengonfigurasi, Mengatur, dan Mengonsolidasikan Tes Cypress Anda
  • Mengintegrasikan Pengujian Cypress Dengan Docker, Buildkite, dan CICD