มาเขียน Web Component Testing ให้ Next.js App ด้วย Cypress กัน

Traitanit Huangsri
Cypress.io Thailand
5 min readMay 2, 2021

สวัสดีครับ บทความนี้จะขอพานักพัฒนาเว็บทุกท่าน มาเขียน Web Component Testing ให้กับ Next.js App ด้วย Cypress กัน ซึ่งจะทำให้คุณมีประสบการณ์การเขียนเทสที่ดีขึ้นอย่างที่ไม่เคยมีมาก่อนแน่นอน

Component Testing คืออะไร ?

เนื่องจากการพัฒนาเว็บในยุคนี้ส่วนใหญ่เราก็จะใช้การ design เว็บของเราออกมาเป็น Component ย่อยๆ เพื่อให้เราสามารถ reuse การใช้งาน Component นั้นๆ ในแต่ละหน้าในเว็บเราได้ ซึ่งการทำ Component Testing ก็คือการหยิบ Component ที่เราสร้างไว้มารันและเทสดูว่ามี behavior เป็นไปตามที่เราต้องการหรือไม่ โดยจะเป็นการเทสแบบ Isolate แยกกันในแต่ละ Component เพื่อ Scope เฉพาะ functionality ของ Component แต่ละอันแยกกัน ซึ่งจะแตกต่างกับการทำ End-to-End Test ที่เราจะ Deploy ประกอบร่างเว็บของเราทั้งหมดแล้วนำไปเทสกับ Server จริงๆ

ซึ่งโดยปกติในการเขียน Test ให้กับ Web Components ของเราก็มักจะนำ Component ไปรันอยู่บน Virtual Browser อย่าง jsdom ซึ่งก็จะมีข้อเสียตรงที่ว่าบาง Browser APIs อาจไม่มีให้ใช้งาน ทำให้เราจะต้องเสียเวลาไป Mock Behavior ของ Browser APIs เหล่านั้นเพื่อให้เราสามารถทำเทสได้

จะดีกว่าไหมถ้าเราสามารถเทส Web Components เราบน Browser จริงได้โดยที่ยังคงไว้ซึ่งการเทสแบบ Isolated Component ได้เช่นเดิม ถ้าคุณเป็นคนหนึ่งที่ต้องการทำเช่นนั้นแล้ว Cypress ก็น่าจะเป็นคำตอบที่จะช่วยให้คุณสามารถรันเทส Web Components บน Browser จริงได้ โดยยังคงไว้ซึ่งการเทส Concept เดิม

Next.js Component Testing with Cypress

โดยในปัจจุบัน ตั้งแต่ Cypress เวอร์ชัน 7.0 ขึ้นไปได้มีการรองรับการทำ Component Testing ให้กับ Web Framework ต่างๆ แล้วไม่ว่าจะเป็น React, Vue และล่าสุดอย่าง Next.js ซึ่งเป็น Web Framework ที่เพิ่มความสามารถต่างๆ เข้าไปมากมายเช่นการทำ Static และ Server Side Rendering, Image Optimization ต่างๆ ซึ่งในบทความนี้เราจะมาดูกันว่าเราจะสามารถเขียน Component Testing ให้กับ Next.js App ได้อย่างไร

1. เริ่มสร้าง Next.js App

เราสามารถสร้าง Next.js App ได้ง่ายๆ โดยใช้ Command

$ npx create-next-app nextjs-cypress-ct

เมื่อเราได้โครงสร้างของ Project มาแล้ว เมื่อลองรันแอพขึ้นมาใน dev environment ก็จะได้หน้าตาออกมาแบบนี้

$ yarn dev

2. ติดตั้ง Cypress และ Test Dependencies ต่างๆ

เมื่อ Project พร้อมใช้งานแล้วให้เราทำการติดตั้ง Cypress เข้าไปใน Next.js project ได้แบบนี้ครับ

$ yarn add -D cypress @cypress/react @cypress/webpack-dev-server @testing-library/cypress html-webpack-plugin webpack webpack-dev-server

เมื่อติดตั้งเสร็จแล้วก็จะเห็น devDependencies ใน package.json แบบนี้ครับ

หลังจากนั้นให้เราทำการรัน Command

$ npx cypress open

เพื่อทำการให้ Cypress ทำการสร้าง folder structure ต่างๆ สำหรับเทสที่จะเขียนด้วย Cypress นั่นเอง

โดย Cypress จะสร้างโฟลเดอร์ cypress ไว้ให้ใน root directory ของ project พร้อมทั้งวาง structure ของโฟลเดอร์ไว้แบบนี้

  • integration: เอาไว้สำหรับเก็บไฟล์ tests ที่เป็น Integration / End-to-End Tests
  • fixtures: เอาไว้สำหรับเก็บไฟล์ที่เป็น test data ต่างๆ
  • plugins: สำหรับ load plugins ต่างๆ ที่จำเป็นขึ้นมาใช้งาน
  • support: สำหรับโหลด support file เช่น custom cypress commands เป็นต้น

3. เริ่มสร้าง Web Component

ในบทความนี้ผมจะลองสร้าง Web Component ตัวอย่างขึ้นมาใช้สำหรับทำเทส โดย Component ที่ว่าจะมีหน้าที่เพื่อ Render Blog Posts ต่างๆ โดยทำการ Fetch Data มาจาก API https://jsonplaceholder.typicode.com/ อีกทีครับ

ผมได้ Apply Best Practice โดยสร้าง Module CSS และ Locator File posts.locator.js เพื่อเก็บ DOM Locator เพื่อให้ Test สามารถเข้าถึง DOM Element ใน Component ได้แบบง่ายๆ ผ่าน Custom Data Attribute (อธิบายเพิ่มเติมภายหลัง) และสามารถให้ Test Case สามารถ reuse ใช้ locator ไฟล์เดียวกันได้ด้วย เพื่อไม่ให้เกิดการ define locators ที่ซ้ำซ้อนกัน

หลังจากนั้นผมทำการแก้ไขไฟล์ index.js ในหน้า Home เพื่อให้ Render Posts Component ในหน้าแรกแบบนี้

เมื่อรันแอพออกมาก็จะได้หน้าตาแบบนี้

หน้า Home ของเรา

4. เริ่มเขียนเทสให้กับ Posts Component

ให้ทำการสร้างโฟลเดอร์ component ในโฟลเดอร์ cypress เพื่อสร้าง Component Test สำหรับ Posts Component

4.1 Inject Next.js Component Testing Plugin เข้าไปใน Cypress

ที่ไฟล์ cypress/plugins/index.js ให้เราทำการเพิ่ม Next.js Component Test Plugin เข้าไปแบบนี้ครับ

โดยตัว plugin จะทำการ inject Next.js webpack-dev-server เข้าไปเพื่อให้ Cypress สามารถเข้าถึงตัว Next.js Component ได้นั่นเอง

4.2 เริ่มเขียน Component Testing

หลักการเขียน Component Testing ก็ไม่ยากครับ เราสามารถใช้ mount API ของ Cypress เพื่อ mount Component รันขึ้นมาใน Browser และหลังจากนั้นเราก็สามารถใช้ Cypress Command ในการเข้าถึง Web Elements ต่างๆ ใน Component ของเราเพื่อทำพวก Assertion ได้เลยแบบนี้

ในตัวอย่างโค้ดนี้ ผมได้ทำการ pass properties เข้าไปยัง Posts Component 2 ค่าด้วยกัน นั่นคือ posts และ users โดยทำการ mock object ให้มีโครงสร้างเหมือนกับที่ได้มาจากการทำ Data Fetching มาจาก API นั่นเอง

นอกจากนี้ผมยังใช้ testing-library/cypress ในการเข้าถึง elements ต่างๆ ผ่านการใช้ custom data attribute (data-testid) ถ้าใครที่เคยใช้พวก React Testing Library ก็คือ Concept เดียวกันเลยครับ

5. Run Component Testing ด้วย Cypress

Cypress ได้เพิ่ม Test Runner ตัวใหม่ชื่อว่า “Cypress Component Test Runner” สำหรับใช้ในการจัดการ Component Test Case ต่างๆ รวมถึงยัง Embed React Developer Tool เข้าไปใน Test Runner ให้ด้วย (ในกรณีที่เราติดตั้งไว้ใน Browser) ทำให้เราสามารถ Debug Properties, State ต่างๆ ที่อยู่ใน Component ณ ขณะที่รันเทสได้เลย เป็น Feature ที่ผมชอบมากๆ เลยครับ

เราสามารถรัน Component Testing ได้ด้วย Command

$ npx cypress open-ct

จะเห็นได้ว่า ข้อแตกต่างของการรัน Component Testing ด้วย Cypress นั่นก็คือเราสามารถมองเห็นหน้าตาของ Component ของเราตอนรันขึ้นมาได้เลย และยังสามารถมองเห็น Element ต่างๆ รวมถึง Properties และ State ต่างๆ ได้อีกด้วย รวมถึงการใช้ Browser APIs ก็สามารถใช้งานได้อย่างเต็มที่โดยที่ไม่ต้อง Mock ใดๆ เลย เพิ่ม Confident ในการทำเทสของเราได้มากขึ้นอีกเยอะเลยครับ

6. สร้าง Code Coverage Report

เมื่อเรารันเทสเสร็จแล้วเราก็คงอยากจะรู้ว่าเทสที่เราเขียนนั้นมันมี Code Coverage เป็นเท่าไร ซึ่งถ้าเราเขียนเทสด้วย Cypress เราก็สามารถสร้าง Code Coverage Report ได้อย่างง่ายๆ เช่นกัน โดยใช้ Cypress Code Coverage Plugin และ Istanbul Babel Plugin ทำงานร่วมกันได้แบบนี้ครับ

6.1 Install Dependencies

$ yarn add -D @cypress/code-coverage babel-plugin-istanbul

6.2 เพิ่ม Code Coverage Task เข้าไปใน Cypress

ที่ไฟล์ cypress/plugins/index.js ให้ Inject Code Coverage Task เพิ่มเข้าไปแบบนี้ครับ

โดย Cypress จะทำการคำนวณ Code Coverage ให้เราอัตโนมัติทุกครั้งที่มีการรันเทสเลยครับ Config ที่นี่ทีเดียว

6.3 Import Code Coverage Plugin เข้าไปใน Cypress

ที่ไฟล์ cypress/support/index.js ให้ทำการเพิ่ม

6.4 เพิ่ม Babel Configuration สำหรับ Istanbul Code Instrumentation
ให้เราทำการสร้างไฟล์ .babelrc ไว้ใน root directory ของ project และ config ค่าของ Babel ไว้แบบนี้

6.5 ลอง Rerun Component Test อีกครั้ง

เมื่อเราทำการ Run Component Testing ใหม่อีกครั้ง ก็จะมีโฟลเดอร์ coverage ถูกสร้างไว้ให้อัตโนมัติและมี Report ได้ถูกสร้างไว้ให้เรียบร้อยแล้วในรูปแบบของ lcov report แบบนี้ครับ

Code Coverage Report

เราสามารถกดเข้าไปดูรายละเอียดในโค้ดเราได้ว่ามีส่วนไหนที่ถูกเทส Cover แล้วบ้างหรือส่วนไหนที่ยังไม่ Cover ได้เลยครับ

สรุป

วันนี้เราสามารถสร้าง Component Testing ให้กับ Next.js App ของเราด้วย Cypress ได้แล้ว และด้วยความสามารถของ Cypress Component Test Runner ก็ยิ่งช่วยทำให้เราสามารถ Debug โค้ดของเราได้ง่ายมากขึ้นและเห็นภาพมากยิ่งขึ้นว่า Component ที่เราสร้างไว้เมื่อรันขึ้นมาหน้าตาเป็นอย่างไร ไม่จำเป็นต้องไปทำ End-to-End Test เสมอไป เพราะการทำ End-to-End Test ก็มี Cost ที่สูงกว่าและเสี่ยงกับการเกิด Test Flakiness ที่มากกว่า

นอกจากนี้เราก็ยังสามารถใช้ Cypress Code Coverage Plugin เพื่อสร้าง Code Coverage Report ได้อย่างง่ายๆ อีกด้วย ผมหวังว่าบทความนี้จะช่วยให้นักพัฒนามีไอเดียใหม่ๆ ในการพัฒนาและเขียน Test บน Next.js App มากขึ้นนะครับ ตัวอย่างโค้ดทั้งหมดในบทความนี้สามารถดูแบบเต็มๆ ได้ที่ลิ้งค์ด้านล่างนี้เลย แล้วพบกันใหม่บทความหน้า Happy Coding! ทุกคนครับบ

--

--