TypeScript ทุกสิ่งในการทดสอบ Cypress ของคุณ #frontend@twiiosendgrid

เผยแพร่แล้ว: 2020-11-14

ที่ Twilio SendGrid เราเขียนเว็บแอปพลิเคชันส่วนหน้าส่วนใหญ่ โดยเฉพาะหน้าและคุณสมบัติใหม่ด้วย TypeScript และ React ในปัจจุบันเพื่อการตรวจสอบประเภทที่ดีขึ้น การบำรุงรักษา และเอกสารประกอบของฐานรหัสของเรา เมื่อเราเริ่มเขียนการทดสอบ Cypress เมื่อสองปีที่แล้ว ออบเจ็กต์เพจ ตัวช่วย และไฟล์ข้อมูลจำเพาะส่วนใหญ่ยังคงใช้งาน JavaScript และส่วนใหญ่เราใช้ Cypress เวอร์ชัน 3.xx การทดสอบล่าสุดมีการเขียนขึ้นใน TypeScript แล้ว แต่เรา ยังมีไฟล์จำนวนมากที่จะแปลงและย้ายไปยัง TypeScript

เราต้องการเก็บเกี่ยวผลประโยชน์จากการพิมพ์ส่วนประกอบ การทดสอบหน่วย และการทดสอบ Cypress E2E ของเรา อย่างเต็มที่ สิ่งที่ทำให้กระบวนการนี้ง่ายขึ้น คือการโยกย้ายไปยัง Cypress เวอร์ชันใหม่กว่าเพื่อใช้ประโยชน์จากการสนับสนุน TypeScript แบบสำเร็จรูปตั้งแต่ Cypress 4.4.0

หากคุณต้องการย้อนกลับไปและเรียนรู้วิธีคิดเกี่ยวกับการเขียนการทดสอบ E2E โดยทั่วไป อย่าลังเลที่จะตรวจสอบโพสต์ในบล็อกนี้ หากคุณต้องการดูภาพรวมหนึ่งพันฟุตของสิ่งที่เราเคยใช้หรือเคยทำมาก่อนด้วยการเขียนการทดสอบ Cypress ในสภาพแวดล้อมที่แตกต่างกัน คุณสามารถอ้างถึงโพสต์ในบล็อกนี้ก่อนที่จะเริ่มเพิ่ม TypeScript ในการทดสอบ Cypress ของคุณ โพสต์ในบล็อกนี้ถือว่าคุณคุ้นเคยกับการทดสอบ Cypress และเคยใช้ API มาก่อน

หากคุณพร้อมที่จะเห็นว่าเราพิมพ์สิ่งต่างๆ ออกมาอย่างไร อันดับแรก มาดูการเปลี่ยนแปลงเบื้องต้นบางอย่าง เช่น การเพิ่มการรองรับ TypeScript ให้กับ Cypress หากคุณมาจากเวอร์ชันที่เก่ากว่า

กำลังย้ายจาก Cypress 3.x เป็น >= 4.4.0

สำหรับผู้ที่ได้กำหนดค่าโครงสร้างพื้นฐาน Cypress ของตนให้ทำงานกับ TypeScript ใน Cypress เวอร์ชัน 3.xx ถึง 4.4.3 แล้ว คุณน่าจะเคยพบกับการทดลองและข้อผิดพลาดในการตั้งค่าการกำหนดค่าตัวประมวลผลล่วงหน้าของ Webpack ที่เหมาะสมใน plugins/index.js ของคุณ สำหรับทีม Twilio SendGrid มี gotchas บางไฟล์ที่มีไฟล์บางไฟล์ที่จำเป็นต้องเป็นไฟล์ JavaScript ใน plugins และโฟลเดอร์ support และข้อผิดพลาด Cypress ที่ยากต่อการดีบักจะปรากฏขึ้น เมื่อคุณได้งานบางอย่างแล้ว ควรมีลักษณะดังนี้


หลังจากอัปเกรดจาก 3.xx เวอร์ชันก่อนหน้า เราสามารถยกเลิกการกำหนดค่าตัวประมวลผลล่วงหน้าของ Webpack แทนที่ไฟล์ plugins/index.js ด้วยไฟล์ index.ts ปรับแต่งเล็กน้อยด้วย tsconfig.json ของโฟลเดอร์ Cypress และสุดท้าย ใช้ไฟล์ TS ในโฟลเดอร์ Cypress ของเรา (เช่น some_page.spec.ts , index.d.ts หรือ page_object.ts ) - ไม่มีการกำหนดค่าตัวประมวลผลล่วงหน้าของ Webpack อีกต่อไปและมันใช้งานได้! เราพอใจกับความสะอาดและดีกว่าที่ไม่ได้จัดการการกำหนดค่าตัวประมวลผลล่วงหน้าของ Webpack ของคุณเองและการครอบคลุม TypeScript ที่ดีกว่าไฟล์ของเราดังที่แสดงด้านล่าง

ด้วยการสนับสนุน TypeScript เราจึงดูตัวอย่างแอปพลิเคชันในโลกแห่งความเป็นจริงของทีม Cypress หรือ repo แอป cypress-real-world-app เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการพิมพ์สิ่งต่าง ๆ ให้ดีขึ้น เราค้นพบวิธีพิมพ์ cy.task(“pluginName”, { … }) และ Cypress.env(“someEnvVar”) ฟังก์ชันเรียกร้องให้มีการเชื่อมโยงที่ดีขึ้นและพิมพ์การสนับสนุน Intellisense เมื่ออัปเดตไฟล์ นอกจากนี้เรายังขุดผ่านเอกสารประกอบของ TypeScript สิ่งนี้สอนเราถึงวิธีพิมพ์สิ่งต่าง ๆ เช่น คำสั่ง cy.login() แบบกำหนดเองของเรา และวิธีตั้งค่าไฟล์การกำหนดค่า tsconfig.json แอปพลิเคชันตัวอย่างยังมี tsconfig.json ให้คุณอ้างอิง ซึ่งสามารถจัดเตรียมการกำหนดค่า TypeScript พื้นฐานที่ยอดเยี่ยมให้คุณปรับแต่งตามความต้องการของคุณ เราขอแนะนำให้คุณติดตาม Cypress เวอร์ชันล่าสุด เจาะลึกแหล่งข้อมูล Cypress อย่างเป็นทางการ และทดลองกับไฟล์คำจำกัดความประเภทของคุณ

การพิมพ์คำสั่งที่กำหนดเอง

เราได้สร้างคำสั่งแบบกำหนดเองระดับโลกบางอย่าง เช่น cy.login() เพื่อจัดการการเข้าสู่ระบบผ่าน API เพื่อให้สามารถใช้ซ้ำได้ตลอดทั้งไฟล์ข้อมูลจำเพาะทั้งหมดของเรา ต่อไปนี้คือตัวอย่างวิธีพิมพ์คำสั่งการเข้าสู่ระบบที่กำหนดเองโดยระบุข้อมูลรับรองผู้ใช้และส่งคืนโทเค็นการตรวจสอบสิทธิ์

ตัวแปรสภาพแวดล้อมการพิมพ์

สำหรับการจัดการกับสภาพแวดล้อมการทดสอบที่หลากหลาย เช่น dev และ staging เราใช้ประโยชน์จากการกำหนดค่าตัวแปรสภาพแวดล้อม เช่น: “testEnv” เพื่อเก็บสภาพแวดล้อมที่เรากำลังทดสอบอยู่ เช่น staging, “apiHost” เพื่อเก็บ backend API host และอื่นๆ ตัวแปร คุณสามารถพิมพ์การ Cypress.env() ของคุณเพื่อพิมพ์ฟังก์ชันและอ็อบเจกต์อื่น ๆ ที่อาศัยการใช้ค่าตัวแปรสภาพแวดล้อมเช่นนี้ได้ดีขึ้น

ปลั๊กอินการพิมพ์

เราได้สร้างฟังก์ชันปลั๊กอิน cy.task() จำนวนมากเพื่อจัดการกับสิ่งต่างๆ จากการเรียก API การสำรวจบริการ และการตรวจสอบอีเมลที่ตรงกันในกล่องขาเข้าอีเมลทดสอบ ก่อนหน้านี้ เมื่อเชื่อมโยงการเรียกใช้ฟังก์ชันเหล่านี้เช่น cy.task().then((data) => {}) หัวเรื่องข้อมูลที่ถูกล่ามโซ่จะถูกพิมพ์เป็น any หรือknown ซึ่งไม่เหมาะสำหรับไฟล์ unknown ของเรา เราค้นพบผ่านตัวอย่าง Cypress วิธีพิมพ์ปลั๊กอินให้ดีขึ้นตามชื่อปลั๊กอินและอาร์กิวเมนต์ที่ส่งผ่านในการเรียกใช้ฟังก์ชัน สิ่งนี้ทำให้ไฟล์ TypeScript ของเราสามารถตรวจพบว่าประเภทข้อมูลที่ถูกล่ามโซ่คืออะไร

ปัญหาที่ละเอียดอ่อนอย่างหนึ่งที่เราพบคือชื่อปลั๊กอินและอาร์กิวเมนต์ต้องตรงกันทุกประการกับวิธีที่คุณพิมพ์ เราพบว่าสิ่งสำคัญคือต้องวางเมาส์เหนือประเภท chained .then( .then() และอ็อบเจ็กต์อาร์กิวเมนต์ cy.task() ในเอดิเตอร์ของคุณเพื่อเพิ่มเป็นสองเท่า ตรวจสอบว่าประเภทตรงกันอย่างถูกต้อง ในบางครั้ง หากคุณใช้หัวเรื่องที่ถูกล่ามโซ่จากฟังก์ชัน Cypress อื่น เช่น cy.getCookie(“auth_token”).its(“value”).then((token) => { }) หรือ cy.wrap(data).then((data) => {}) คุณต้องพิมพ์อาร์กิวเมนต์ data ที่ถูกล่ามโซ่เหล่านั้นด้วยก่อนที่จะส่งผ่านเป็นอาร์กิวเมนต์ของ cy.task(..., { token, data }) ไม่เช่นนั้นคุณจะยังเห็น cy.task(...).then((data) => { }) ส่วนข้อมูลถูกพิมพ์เป็น any หรือ unknown คุณควรมีความชัดเจนมากขึ้นในประเภทฟังก์ชัน Cypress ที่ถูกล่ามโซ่ไว้มากมาย เช่น .its(“value”).then((token: string) => {}) หรือ cy.wrap(data).then((data: DataType) => {}) ก่อนส่งต่อโดยเป็นส่วนหนึ่งของวัตถุอาร์กิวเมนต์ cy.task() เพื่อให้แน่ใจว่าประเภทจะทำงานอีกครั้ง

เราได้สร้างไฟล์ typescript ของปลั๊กอินแยกต่างหากที่จะส่งออกฟังก์ชันเพื่อใช้ใน plugins/index.ts ของเรา เมื่อจำนวนปลั๊กอินเพิ่มขึ้น เราขอแนะนำให้คุณจัดระเบียบการใช้งานฟังก์ชันปลั๊กอินเหล่านี้ตามหน้าหรือคุณลักษณะเพื่อให้ไฟล์ plugins/index.ts ของคุณมีขนาดเล็ก คุณควรทำให้อ่านได้อย่างรวดเร็วโดยสรุป โดยที่คุณกำหนด cy.task(...) ทั้งหมดของคุณในไฟล์ plugins/index.ts ในที่สุด คุณสามารถพิมพ์ฟังก์ชันงานเหล่านี้ใน index.d.ts ด้วยวิธีต่อไปนี้:

รวมทุกอย่างไว้ในไฟล์ประกาศประเภท

เราใส่คำสั่งแบบกำหนดเอง ตัวแปรสภาพแวดล้อม และปลั๊กอินทุกประเภทของเราไว้ในไฟล์ index.d.ts ในโฟลเดอร์ support เราขอแนะนำให้คุณวางประเภท Cypress ทั้งหมดของคุณไว้ในไฟล์คำจำกัดความของ TypeScript หลักเพื่อจัดระเบียบสิ่งต่างๆ สำหรับการข้ามประเภทที่ขาดหายไปในการพึ่งพาภายนอกที่ใช้ในโค้ดทดสอบ Cypress ของคุณ คุณอาจกำหนดไฟล์โมดูล เช่น “some-lib.d.ts” ซึ่งรวมถึง declare module 'some-lib' เพื่อแก้ไขปัญหาคำเตือน TypeScript ของไลบรารี คุณยังสามารถใช้คุณลักษณะประเภทการนำเข้าของ TypeScript เพื่อนำเข้าประเภท/อินเทอร์เฟซที่กำหนดไว้ภายในไฟล์ปลั๊กอิน/ยูทิลิตี้อื่นๆ ของคุณ เพื่อหลีกเลี่ยงไม่ให้คำจำกัดความประเภทของคุณซ้ำกันในหลายไฟล์ คุณสามารถเพิ่มประเภทเหล่านี้ภายในเนมสเปซ Cypress และจัดระเบียบด้วยวิธีต่อไปนี้:

การพิมพ์อ็อบเจ็กต์ฟิกซ์เจอร์ทดสอบ ออบเจ็กต์ของเพจ และไฟล์ข้อมูลจำเพาะ

เมื่อเราต้องการโหลดผู้ใช้และข้อมูลเมตาที่แตกต่างกันสำหรับสภาพแวดล้อมการทดสอบ ก่อนหน้านี้เราได้แสดงให้เห็นวิธีที่เราสามารถรวมตัวแปรสภาพแวดล้อม เช่น “testEnv” กับค่าของ “การทดสอบ” หรือ “การจัดเตรียม” เพื่อแยก “การทดสอบ” หรือ “ staging” วัตถุจากวัตถุติดตั้งทดสอบโดยรวม คุณสามารถพิมพ์อ็อบเจ็กต์สภาพแวดล้อมของฟิกซ์เจอร์ทดสอบเหล่านี้ด้วยข้อมูลทั่วไปสำหรับโครงสร้างที่สอดคล้องกันสำหรับข้อมูลจำเพาะทั้งหมดของคุณเพื่อแชร์ สำหรับแต่ละสภาพแวดล้อมการทดสอบ คุณสามารถมีข้อมูลรับรองผู้ใช้และฟิลด์เมตาเดียวกันได้โดยใช้ประเภททั่วไปสำหรับการทดสอบเพื่อเพิ่มคุณสมบัติได้มากเท่าที่ต้องการ ดูตัวอย่างด้านล่าง

การพิมพ์ออบเจ็กต์ของเพจและการพิมพ์ไฟล์ข้อมูลจำเพาะที่เกี่ยวข้องนั้นขึ้นอยู่กับคำสั่ง Cypress, ปลั๊กอิน และโปรแกรมอรรถประโยชน์อื่นๆ ที่คุณใช้อยู่ ส่วนใหญ่ การพิมพ์ออบเจ็กต์หน้าหรือไฟล์ข้อมูลจำเพาะไม่ต้องการการเปลี่ยนแปลงมากมายจาก JavaScript ของพวกมัน (สมมติว่าคุณพิมพ์ปลั๊กอินและการเรียกตัวแปรสภาพแวดล้อมแล้ว) ในบางครั้ง ฟังก์ชันตัวช่วยออบเจ็กต์เพจที่คุณกำหนดอาจจำเป็นต้องพิมพ์อาร์กิวเมนต์บางตัว หรืออาจจำเป็นต้องพิมพ์การตอบสนองที่กลับมาจากการเรียก cy.request() as response.body as SomeType โดยรวมแล้ว โปรแกรมแก้ไขของคุณ เช่น VSCode สามารถตรวจหาประเภทสายโซ่ของการ cy.task() หรือ cy.customCommand() ได้โดยอัตโนมัติ โดยที่คุณไม่ต้องเพิ่มประเภทอื่นๆ ในไฟล์ข้อมูลจำเพาะเพื่อชดเชยการเตือน TypeScript

นี่คือตัวอย่างบางส่วนของออบเจ็กต์เพจที่มีฟังก์ชันตัวช่วยและไฟล์ข้อมูลจำเพาะที่ใช้ออบเจกต์เพจ คำสั่งล็อกอินแบบกำหนดเอง และงานปลั๊กอิน

บทสรุป

การเพิ่ม TypeScript ในการทดสอบ Cypress ช่วยให้เราหลีกเลี่ยงจุดบกพร่องและปรับปรุงประสบการณ์ของนักพัฒนาเมื่อเขียนการทดสอบ Cypress เมื่อใช้ cy.task() , Cypress.env() และ cy.customCommand() การเรียกใช้ฟังก์ชัน เราสามารถตรวจสอบประเภทที่ดีขึ้นในอาร์กิวเมนต์และเอาต์พุตของฟังก์ชัน ตลอดจนใช้ประโยชน์จากการเติมโค้ดให้สมบูรณ์ใน IDE ของเรา เช่น VSCode

กุญแจสำคัญคือการสร้างไฟล์ประกาศประเภทของคุณเอง เช่น ไฟล์ index.d.ts ซึ่งคุณสามารถแทนที่หรือขยายอินเทอร์เฟซ "Cypress" และ "Chainable" ตามคำสั่งที่กำหนดเอง ตัวแปรสภาพแวดล้อม และฟังก์ชันปลั๊กอินงานที่คุณเป็น โดยใช้. ในวัตถุเพจและไฟล์ TypeScript ข้อมูลจำเพาะ คุณสามารถใช้ฟังก์ชัน Cypress เหล่านั้นและเลื่อนเมาส์ไปวางเหนือหรือทำตามคำจำกัดความของประเภทอินพุตและเอาต์พุตที่คาดไว้

ยิ่งกว่านั้น ลองใช้ TypeScript กับ Cypress เนื่องจากมีการรองรับ TypeScript ในเวอร์ชันล่าสุด ทดสอบว่าจะช่วยให้คุณทำงานเอกสารได้ชัดเจนขึ้นหรือไม่ และหลีกเลี่ยงการใช้ API ที่ไม่ถูกต้อง การทดสอบ TypeScript ของคุณน่าจะยังคล้ายกับการทดสอบ JavaScript Cypress ของคุณ ดังนั้นคุณจึงสามารถแปลงการทดสอบบางรายการในแต่ละครั้งอย่างต่อเนื่องเพื่อเปรียบเทียบและเปรียบเทียบแนวทางต่างๆ

หากคุณสนใจบทความเพิ่มเติมเกี่ยวกับสิ่งที่เราได้เรียนรู้จากการทดสอบ Cypress ต่อไปนี้คือบทความบางส่วนที่คุณควรตรวจสอบ:

  • สิ่งที่ต้องพิจารณาเมื่อเขียนการทดสอบ E2E
  • ภาพรวม 1,000 ฟุตของการเขียนแบบทดสอบ Cypress
  • การจัดการกับกระแสอีเมลในการทดสอบ Cypress
  • แนวคิดสำหรับการกำหนดค่า การจัดระเบียบ และการรวมการทดสอบ Cypress ของคุณ
  • การรวมการทดสอบ Cypress กับ Docker, Buildkite และ CICD