ครั้งแรกกับการรองรับ Component Testing อย่างเต็มรูปแบบบน Cypress ที่จะทำให้การเขียนเทสของคุณเปลี่ยนไปตลอดกาล

Traitanit Huangsri
Cypress.io Thailand
5 min readApr 6, 2021

ถือว่าสมกับการรอคอยจริงๆ สำหรับ Feature ใหม่ของ Cypress 7.0.0 ที่ประกาศรองรับการเขียน Component Testing อย่างเต็มรูปแบบ ผมได้ลองใช้ Feature นี้แล้วต้องบอกว่า “ว้าว” มากครับ วันนี้ผมจะมาแนะนำให้ทุกคนได้รู้จักและได้เริ่มเขียน Component Testing ไปพร้อมกันในบทความนี้เลยครับ

Component Testing คืออะไร?

ปกติแล้วในการพัฒนา Web Application ในยุคนี้แล้วส่วนใหญ่นักพัฒนาก็มักจะนิยมนำแนวคิดของการสร้าง “Web Components” มาใช้ในการพัฒนาเป็นส่วนใหญ่เลย และรวมถึง Web Frameworks ยอดนิยมในยุคนี้ก็นำแนวคิดนี้มาใส่อยู่ใน Framework ของตัวเองกันหมด ไม่ว่าจะเป็น React.js, Vue.js หรือ Angular.js ก็ตาม ด้วยเหตุผลที่ว่าเราจะได้ reuse components ที่เราสร้างไว้ได้ในหลายๆ Page ที่อยู่ใน Web Application ของเรานั่นเอง

ซึ่งปกติแล้วเวลาที่เราจะต้องการเขียนเทส Web Components ของเรานั้น เราก็มักที่จะนำ Component ที่เราสร้างขึ้นมานำมารันอยู่บน Node.js testing framework อย่าง jest หรือ mocha ซึ่ง Component ของเราก็จะถูกรันอยู่บน “Virtual Browser” ที่บางคนอาจจะรู้จัก ซึ่งนั่นก็คือ jsdom นั่นเอง

ส่วนตัวผมเองก็มีประสบการณ์การเขียน Component Testing บน jsdom แล้วก็พบปัญหาบางอย่างเช่น

  1. ไม่ Fully Support Browser APIs ทุกตัว เช่น การทำ Navigation ด้วย location Object เป็นต้น ต้องคอยมานั่ง Mock Behavior ของ Browser APIs เพื่อให้เทสรันได้
  2. Debuggability ที่ทำได้ค่อนข้างยาก และทำได้ลำบาก เพราะมันไม่ได้มี UI รันขึ้นมาให้เราเห็นภาพได้จริงๆ บางครั้งแทบจะต้องจินตนาการ Fix โค้ดกันเลย

Cypress ได้มองเห็นจุดนี้และอยากทำให้ Component Testing ทำง่ายขึ้นกว่าเดิมและต้องดีกว่าเดิมด้วยการที่ทำให้เราสามารถนำ Component ของเราขึ้นไปเทสบน “Real Browser” จริงได้ แต่ยังคงไว้ซึ่ง Concept “test a component in isolation” ไว้เช่นเดิม ซึ่งจะทำให้เราสามารถมองเห็นได้ชัดเจนมากขึ้นว่า Component ของเราเมื่อถูกนำไปเทสแล้วมันทำงานอย่างไร

ข้อดีอีกอย่างที่เมื่อเราสามารถนำ Web Components ขึ้นไปรันบน Real Browser ด้วย Cypress ก็คือ เราสามารถใช้ Feature ทุกอย่างที่ Cypress รองรับกับการทำ E2E Test ได้เลยไม่ว่าจะเป็น

  • Automatic Waits for Elements
  • Realtime Reloads (Hot-Reload)
  • Time Travel ย้อนกลับไปดู Step ที่ Failed ได้
  • Test Runner ที่ช่วยให้เรามองเห็นเทสได้อย่างชัดเจนแบบ Step by Step
  • Dashboard Service ที่ช่วยเก็บผลเทสของเราและทำ Analytics ให้ได้อีกด้วย
  • อื่นๆ เช่น ​Stub & Spy, Code Coverage ที่ Cypress เตรียมพร้อมไว้ให้ใช้งานได้เลย

นี่ยังไม่รวมถึง Cypress Commands และ APIs ที่พร้อมให้เรานำมาใช้งานในการทำ Component Testing ได้อีกมากมาย ซึ่งจะทำให้เราเขียนเทสได้ง่ายขึ้น เทสได้เหมือนการใช้งานจริงมากขึ้น และ Debug โค้ดของเราได้ดีขึ้นอีกมากๆ เลย

มาเริ่มลองสร้าง Component Testing ด้วย ​Cypress กัน

ในบทความนี้ผมจะใช้ React เป็นตัวอย่างของการเขียน Web Component Testing กันนะครับ ซึ่ง ณ​ ตอนนี้คุณสามารถใช้ Cypress ทำ Component Testing ได้ทั้งบน React และ Vue.js เลย

ผมได้ทำการสร้าง Web Application ใหม่โดยใช้ Create-React-App สร้าง Project ขึ้นมา โดยผมจะพัฒนาเว็บง่ายๆ ที่ใช้สำหรับ Add Todo List ของเราแบบนี้ครับ

Simple Todo List App

1. เริ่มต้นสร้าง Project

sh$ npx create-react-app todo-list --template typescript

2. Add Web Components

เมื่อสร้าง Project สำเร็จแล้ว ผมทำการเพิ่ม Components เข้าไป 2 อันก็คือ

  • TodoList เอาไว้สำหรับเพิ่ม Todo Task เข้าไป
  • TodoItem เอาไว้สำหรับ Render Todo Task ที่เราได้เพิ่มเข้าไปในแต่ละอัน

โค้ดของ TodoList Component ก็ simple มากครับ ทำการ handle เมื่อ user พิมพ์ text เข้ามาและกด Enter ก็ให้ทำการ Add Item เข้าไปใน TodoItem ด้วย React Component State ที่สร้างไว้

ส่วน TodoItem Component ก็รับค่า Todo Task โดยส่งผ่านมายัง ​Component Props แล้วนำมา Render โดยมี Checkbox ให้ User สามารถ Check ได้ว่าได้ทำ Task นั้นไปหรือยัง ถ้าทำแล้วก็ให้ Update Stylesheet โดย strikethrough task นั้นออกไป เมื่อรันทั้งหมดออกมาก็จะเห็นการใช้งานแอพแบบนี้ครับ

การใช้งานจริงของ Todo App

3. ติดตั้ง ​Cypress สำหรับทำ Component Testing

ให้เราทำการ Install Cypress เป็น devDependencies ของ Project เข้าไปแบบนี้ครับ

sh$ yarn add -D cypress @cypress/react @cypress/webpack-dev-server

เมื่อติดตั้งเรียบร้อยแล้ว ให้ทำการรันคำสั่ง

sh$ npx cypress open

เพื่อทำการ Initialize Folder Structure ของ Cypress ออกมาครับ (ทำเฉพาะเมื่อเราเพิ่ง Install เป็นครั้งแรกก็พอนะ)

หลังจากนั้นให้เราทำการ Configure ไฟล์ cypress.json เพื่อกำหนด Path ที่เราได้วาง Web Components ของเราไว้ ซึ่งในกรณีนี้ของผมไฟล์ Components จะอยู่ใน src folder ซึ่งเป็นค่า default ของ create-react-app นะครับ

หลังจากนั้นให้เราทำการแก้ไขไฟล์ cypress/plugins/index.js เพื่อทำการ Configure Component Testing Plugin ของ Cypress โดยในกรณีที่เราสร้าง Project ด้วย create-react-app ให้ config plugin แบบนี้ครับ

4. เริ่มเขียน Component Testing

เอาล่ะ ถึงเวลามาเริ่มเขียน Component Testing กันแล้ว หลักการก็ง่ายๆ เลยครับ ให้เราทำการ mount Component ของเราขึ้นมา แล้วเราก็จะสามารถ Test สิ่งต่างๆ ที่อยู่ใน Component ของเราได้ผ่าน Cypress Command ได้เลย (โดยที่ไม่ต้องใช้ cy.visit() เลยนะครับ)

นี่คือไฟล์ TodoList.spec.tsx ที่อยู่ใน src/components ที่เดียวกับ Source Code ของเราโดยผมได้เขียนเทสแบบง่ายเช็ค UI Properties ต่างๆ ที่แสดงผลอยู่ใน Component รวมถึง Action ต่างๆ ที่ User สามารถทำได้กับ Component เช่นข้อ 3 ที่ Simulate การเพิ่ม Task เข้าไปใน ​TodoList ได้นั่นเอง

จะเห็นได้ว่ารูปแบบการเขียน Component Testing นั้นไม่ได้ต่างกับการเขียน E2E Testing ด้วย Cypress เท่าไร เพียงแต่ที่เราไม่ต้องทำการ Navigate ไปที่ URL ของ Web App เราจริงๆ สิ่งที่สำคัญคือ Cypress ได้เตรียม mount API มาให้เราสามารถใช้ Mount Component ขึ้นมาเพื่อใช้งานจริงได้ ซึ่งถือว่าสะดวกมากๆ เลยครับ

5. รัน ​Component Testing ด้วย Cypress Component Test Runner

ในเวอร์ชัน 7.0 นี้ Cypress ได้สร้าง Test Runner ตัวใหม่ขึ้นมาให้ใช้ทำ Component Testing โดยเฉพาะ (คนละตัวกับที่ใช้รัน E2E Test) ซึ่ง Test Runner นี้จะช่วยให้เรามองเห็นได้เลยว่าตอนที่ Component ที่เราเขียนขึ้นมาถูกเทส หน้าตามันเป็นยังไง และมันมีอะไรเกิดขึ้นบ้าง

เราสามารถรัน Cypress Component Test Runner ได้โดยใช้ Command

sh$ npx cypress open-ct

เมื่อรันขึ้นมาแล้วก็จะเห็นเป็นหน้าตาแบบนี้ มันจะทำการ Scan หา Tests ที่เราเขียนไว้ให้อัตโนมัติแล้วก็มี Filter ให้เรา search หา tests ของเราได้ (เหมาะมากตอนที่เรามีเทสเยอะๆ แล้ว) และก็ยังวาดออกมาเป็น Folder Structure ให้เราดูได้ง่ายๆ อีกด้วย เมื่อเราคลิกไปที่แต่ละ Test File มันก็จะเริ่มรันเทสให้แบบนี้ครับ

Component Test Runner in Action

จะเห็นได้ว่าเราสามารถย้อนกลับไปดู Test ของเราในแต่ละ Step ในทุกๆ ข้อได้เลย (เพราะนี่คือหนึ่งใน Feature สำคัญของ Cypress คือ Time Travel กลับได้เสมอ) ในตัวอย่างจะเห็นว่ามันรันเฉพาะ Component ที่เรากำลังเทสดู ดังนั้นอาจจะไม่เห็นพวก CSS ต่างๆ อยู่ในนั้น เรียกได้ว่าเข้าตรงตาม Concept การทำ Component Testing เลยก็คือ Focus ที่ Component Under Test จริงๆ

และนอกจากนี้หากใน Browser ของเรามีการติดตั้ง React Developer Tools Extension ไว้เราก็สามารถ Debug ดูค่า Props และ State ต่างๆ ของ React Components เราผ่าน Cypress Component Test Runner ได้เลยอีกด้วย ส่วนตัวผมชอบ Feature นี้มากๆ มันทำให้เราเปิดโลกการ Debug ได้ง่ายขึ้นมากอย่างชัดเจนครับ

ความเร็วในการรันเทสไม่ต้องพูดถึง เร็วแรงไม่ต่างกับการรันบน Virtual Browser เลย ในตัวอย่างนี้ผมรันเทส 3 ข้อใช้เวลาเพียง 0.86 วินาที ไม่ถึง 1 วินาทีด้วยซ้ำ

นอกจากนี้เรายังสามารถรัน Component Testing แบบที่ไม่ต้องมี Test Runner ขึ้นมาให้ดูได้เช่นกัน เหมาะสำหรับเวลาที่เราต้องการนำไป Integrate กับระบบ Continuous Integration ต่างๆ ก็สามารถทำได้เลยแบบนี้ครับ

sh$ npx cypress run-ct

โดย default มันจะรันกับ Electron.js แบบ headless แต่ถ้าเราอยากจะระบุ Browser ที่ต้องการจะรันก็สามารถใช้ option ได้ เช่นถ้าต้องการรันบน Chrome ก็ทำได้ตามนี้

sh$ npx cypress run-ct --browser chrome

เมื่อรันเสร็จแล้วก็จะมี Report สรุปผลมาให้เราดู รวมถึง Video Capture ไว้ให้เราได้ดูย้อนหลังได้ด้วย จะอยู่ที่ cypress/videos/components/<testFileName.mp4>

บทสรุป

ผมเรียกได้ว่านี่คือการเปิดมิติใหม่ของการเขียน Component Testing ที่จะทำให้เราได้มีรูปแบบใหม่ๆ ในการเขียนเทสที่เทสได้เหมือนจริงมากขึ้น (รันบน Browser จริง) และ Debug โค้ดของเราได้ง่ายขึ้น และยังคงไว้ซึ่ง Concept การเขียนเทสที่ดีคือ “test a component in isolation” และยังทำให้เราสามารถต่อยอดนำเทสของเราไป Integrate ร่วมกับระบบ Continuous Integration ที่มีอยู่แล้วได้อีกด้วย

สำหรับใครที่สนใจอยากลองเขียน Component Testing ด้วย Cypress สำหรับ Web Framework อื่น เช่น Vue.js สามารถเข้าไปอ่านหาข้อมูลเพิ่มเติมได้ที่นี่เลยครับ

และสำหรับใครที่มีข้อสงสัยอื่นๆ สามารถเข้าไปสอบถามกันได้ที่กลุ่ม Cypress.io Thailand ใน Facebook Group ได้เลยครับ ในนั้นมีผู้เชี่ยวชาญรอให้คำตอบคุณอยู่มากมาย และอย่าลืมกด Like, Follow Page Cypress.io Thailand ด้วยนะครับ

อ้อเกือบลืม! ทุกคนสามารถเข้าไปดูโค้ดตัวอย่างในบทความนี้ทั้งหมดได้จาก ​GitHub ลิ้งค์ที่ผมแปะไว้ท้ายบทความนี้เลย หวังว่าบทความนี้จะมีประโยชน์กับหลายๆ คนนะครับ Happy Coding!

--

--