เข้าไปอ่านบทความเรื่อง Refactoring React จาก 8thlight  มา
ทำการอธิบายเกี่ยวกับการ Refactor หรือการปรับปรุงโครงสร้างของระบบที่พัฒนาด้วย React
จาก React แบบปกติ ไปจนถึง ELM Architecture

มีความน่าสนใจและมีประโยชน์ต่อการพัฒนาระบบงานอย่างมาก
จึงทำการแปลและสรุปเพื่อเก็บไว้อ่าน
รวมทั้งฝึกการเขียน code และชุดการทดสอบไปในตัวอีกด้วย

ทำการแบ่งออกเป็น 2 ส่วน เนื่องจากมีรายละเอียดที่เยอะพอสมควรคือ

  1. การพัฒนาและทดสอบ React app
  2. การปรับปรุงโครงสร้างของ React app ให้เป็นไปตาม ELM Architecture

มาเริ่มในส่วนแรกกันดีกว่า

ในบทความเริ่มด้วยคำถามนี้ ซึ่งน่าสนใจมากคือ

How should i best test my React components ?

เรื่องของการทดสอบ React app และ Component นั้น
มันเป็นเรื่องที่ซับซ้อนสับสนวุ่นวายอย่างมาก
เนื่องจาก React เอง
มีทั้งเรื่องของ DOM (Document Object Model)
มีทั้งเรื่องของ State
มีทั้งเรื่องของการแสดงผล
มีทั้งเรื่องของ Life cycle
ซึ่ง React ได้นำส่วนต่าง ๆ เหล่านี้เข้ามาไว้ด้วยกัน
จะเรียกหรือใช้งานบ่อย ๆ คือ Component นั่นเอง

ดังนั้นการทดสอบ React นั้นจะต้องทดสอบในระดับของ Component กันเลย

พูดไปมันไม่เห็นภาพ มาเขียน code กันดีกว่า

โดยบทความนี้จะทำการสร้าง Simple Counter App
เป็น app ที่เพิ่มหรือลบตัวเลขเท่านั้น
ดังนั้นมีปุ่มบวก ปุ่มลบ และการแสดงตัวเลข
ซึ่งมันง่ายมาก ๆ

สามารถเขียนได้ดังนี้

จาก code นั้นเป็นอะไรที่ง่ายมาก ๆ
แต่ว่าถูก layer ของ React ซ่อนความซับซ้อนไว้เพียบ เช่น

  • การทำ caching ค่าของ component
  • การกำหนดค่าเริ่มต้นของ state จากตัวอย่างคือ counter
  • ในส่วนของการ render ก็มีการจัดการข้อมูลจาก state รวมทั้ง callback ต่าง ๆ เพื่อจัดการกับ action/event ที่เกิดขึ้น คือ การกดปุ่มเพื่อเพิ่มหรือลดค่า counter

จากนั้นเพื่อให้เข้าใจมากขึ้น มาเขียนชุดการทดสอบกันดีกว่า

รวมทั้งทำให้เรามั่นใจอีกว่า
ถ้าเราต้องการแก้ไขโครงสร้าง และ reactor app ของเราแล้ว
จะไม่ทำให้การทำงานเปลี่ยนไป
หรือทำให้เรารู้ได้ทันทีว่าเกิดข้อผิดพลาดตรงส่วนไหนบ้าง
ไม่ใช่การทำไปเรื่อย ๆ หรือตามอารมณ์อีกต่อไป

การเขียน test สำหรับ React app นั้นมีทางเลือกเยอะมาก ๆ
ทั้ง Jest, Karma, Mocha, Chai และ Enzyme เป็นต้น
แต่ในบทความนี้เลือกใช้ Enzyme + mocha/chai

ซึ่ง Enzyme จะทำการจำลอง React component lifecycle ขึ้นมา
ทำให้เราสามารถทดสอบ React app/component ได้ง่ายขึ้น

มาเริ่มกันเลย

ก่อนที่จะเขียนสิ่งที่เราควรต้องคิดและออกแบบก่อนคือ

ต้องทำการทดสอบอะไรบ้าง ?
เนื่องจากเป็นการทดสอบในมุมมองของผู้ใช้งาน หรือ ผ่าน User Interface
ดังนั้นชุดการทดสอบจะประกอบไปด้วย

  • ในหน้าจอประกอบไปด้วย 2 ปุ่ม คือ ปุ่มบวกและลบ
  • ค่าเริ่มต้นต้องเป็น 0
  • เมื่อกดปุ่มบวก ค่าต้องเพิ่มขึ้นมา 1
  • เมื่อกดปุ่มลบ ค่าต้องลดลงไป 1
  • เมื่อกดปุ่มบวกและลบไปมา ค่าที่แสดงต้องเป็นไปตามที่คาดหวัง

สิ่งที่ได้เรียนรู้จากการเขียนชุดการทดสอบด้วย Enzyme

ประกอบไปด้วย

  • การติดตั้ง library ที่ต้องใช้งาน
  • การใช้งาน Enzyme เพื่อจำลอง React component และทดสอบ component
  • การใช้งาน Chai สำหรับการ assertion หรือตรวจสอบผลการทำงาน

เมื่อทำการเขียนชุดการทดสอบแล้ว ลองกลับมาดูระบบงานกันหน่อย

ถึงตรงนี้เราทำการทดสอบระบบงานในรูปแบบของ End-to-End testing ?
ตอนนี้เรากำลังทดสอบ framework หรือ framework testing หรือไม่ ?
ประเด็นคือเราผูกติดไปกับ framework มากเกินไปหรือไม่ ?
ส่วนการทำงานหลัก หรือ business logic อยู่ตรงไหน ?
เราสามารถแยกออกมาเพื่อทดสอบได้หรือไม่ ?

สิ่งที่เราควรให้ความสำคัญคือ

  • การจัดการ state
  • การเพิ่มหรือลดค่า
  • การเชื่อมต่อ event ของแต่ละปุ่ม นั่นคือปุ่มบวกต้องเพิ่มค่า ปุ่มลบต้องลดค่า
  • การแสดงผลตัวเลขของ counter

โดยสิ่งต่าง ๆ เหล่านี้ไม่ได้เกี่ยวข้องหรือใช้งาน lifecycle ของ React เลย
React มีหน้าที่เพียงเชื่อมโยงส่วนต่าง ๆ เข้าด้วยกัน (Integration)

ดังนั้นสิ่งที่เราต้องทำกันต่อไปคือ แยกส่วนการทำงานต่าง ๆ ออกจากกัน

จากนั้นทำการทดสอบในแต่ละส่วน
สุดท้ายนำมาผูกหรือเชื่อมต่อกันใน React app

โดยใน React community นั้นนิยมใช้งาน Redux
แต่ในบทความนี้ไม่ต้องการที่จะติดตั้ง Redux หรือ library อื่น ๆ เพิ่มเข้ามาอีก
เนื่องจากทำให้ระบบมีความซับซ้อนมากยิ่งขึ้น
และต้องการใช้งาน pure JavaScript เท่านั้น

โดย source code อยู่ที่ Github :: Up1 :: Learn React to ELM

ในบทความส่วนที่ 2 จะทำการอธิบายเกี่ยวกับ ELM architecture
และขั้นตอนการพัฒนาต่อไป
ซึ่งมันสนุกสนานและน่าสนใจอย่างมาก