พิจารณาสิ่งที่ต้องทดสอบและสิ่งที่ตัดออกได้
บทความก่อนหน้าได้อธิบายข้อมูลเบื้องต้นเกี่ยวกับเทสเคสและสิ่งที่มีในเทสเคส บทความนี้จะเจาะลึกการสร้างกรณีทดสอบจากมุมมองทางเทคนิค โดยอธิบายรายละเอียดว่าควรรวมอะไรไว้ในการทดสอบแต่ละครั้งและควรหลีกเลี่ยงอะไร โดยพื้นฐานแล้ว คุณจะได้ทราบคำตอบสำหรับคำถามเก่าๆ อย่าง "ควรทดสอบอะไร" หรือ "ไม่ควรทดสอบอะไร"
หลักเกณฑ์และรูปแบบทั่วไป
โปรดทราบว่ารูปแบบและจุดที่เฉพาะเจาะจงมีความสําคัญ ไม่ว่าคุณจะทำการทดสอบหน่วย การผสานรวม หรือการทดสอบจากต้นจนจบ หลักการเหล่านี้สามารถใช้และควรใช้กับการทดสอบทั้ง 2 ประเภท จึงถือเป็นจุดเริ่มต้นที่ดี
ทำให้เรียบง่าย
สิ่งสำคัญอย่างหนึ่งที่ควรคำนึงถึงเมื่อเขียนการทดสอบคือความเรียบง่าย คุณควรคำนึงถึงความสามารถของสมอง โค้ดเวอร์ชันที่ใช้งานจริงหลักใช้พื้นที่มาก จึงเหลือพื้นที่ไม่มากนักสำหรับความซับซ้อนเพิ่มเติม โดยเฉพาะอย่างยิ่งสำหรับการทดสอบ
หากมีพื้นที่ว่างน้อยลง คุณอาจผ่อนคลายมากขึ้นในการทดสอบ ด้วยเหตุนี้ การให้ความสำคัญกับความเรียบง่ายในการทดสอบจึงถือเป็นสิ่งสําคัญ อันที่จริง แนวทางปฏิบัติแนะนำสำหรับการทดสอบ JavaScript ของ Yoni Goldberg เน้นความสำคัญของกฎทองที่ว่า "การทดสอบควรเป็นเหมือนผู้ช่วย ไม่ใช่สูตรคณิตศาสตร์ที่ซับซ้อน" กล่าวคือ คุณควรเข้าใจความตั้งใจของการทดสอบได้ตั้งแต่แรกเห็น
คุณควรมุ่งเน้นความเรียบง่ายในการทดสอบทุกประเภท ไม่ว่าจะซับซ้อนเพียงใดก็ตาม อันที่จริง ยิ่งการทดสอบซับซ้อนมากเท่าใด ก็ยิ่งต้องลดความซับซ้อนลงมากเท่านั้น วิธีหนึ่งในการบรรลุเป้าหมายนี้คือการออกแบบการทดสอบแบบ Flat ซึ่งการทดสอบจะเรียบง่ายที่สุดเท่าที่จะเป็นไปได้ และทดสอบเฉพาะสิ่งที่จำเป็นเท่านั้น ซึ่งหมายความว่าการทดสอบแต่ละครั้งควรมีกรณีทดสอบเพียงรายการเดียว และกรณีทดสอบควรมุ่งเน้นที่การทดสอบฟังก์ชันการทำงานหรือฟีเจอร์ที่เฉพาะเจาะจงรายการเดียว
ลองมองจากมุมนี้ว่าควรระบุสิ่งที่ผิดพลาดได้ง่ายๆ เมื่ออ่านการทดสอบที่ไม่ผ่าน ด้วยเหตุนี้ การทดสอบจึงควรทำได้ง่ายและเข้าใจง่าย ซึ่งจะช่วยให้คุณระบุและแก้ไขปัญหาได้อย่างรวดเร็วเมื่อเกิดปัญหาขึ้น
ทดสอบว่าสิ่งใดคุ้มค่า
การออกแบบการทดสอบแบบแบนยังช่วยส่งเสริมให้มุ่งเน้นและช่วยให้การทดสอบของคุณมีความหมาย โปรดทราบว่าคุณไม่ควรสร้างการทดสอบเพียงเพื่อครอบคลุมเนื้อหา แต่ควรมีจุดประสงค์เสมอ
อย่าทดสอบรายละเอียดการใช้งาน
ปัญหาที่พบได้ทั่วไปอย่างหนึ่งในการทดสอบคือ การทดสอบมักออกแบบมาเพื่อทดสอบรายละเอียดการใช้งาน เช่น การใช้ตัวเลือกในคอมโพเนนต์หรือการทดสอบจากต้นทางถึงปลายทาง รายละเอียดการใช้งานหมายถึงสิ่งที่ผู้ใช้โค้ดของคุณมักจะไม่ได้ใช้ ดู หรือแม้แต่ไม่รู้ ซึ่งอาจทำให้เกิดปัญหาหลัก 2 อย่างในการทดสอบ ได้แก่ ผลลบลวงและผลบวกลวง
ผลลบที่ไม่ถูกต้องเกิดขึ้นเมื่อการทดสอบไม่สําเร็จ แม้ว่าโค้ดที่ทดสอบจะถูกต้องก็ตาม ซึ่งอาจเกิดขึ้นเมื่อรายละเอียดการติดตั้งใช้งานมีการเปลี่ยนแปลงเนื่องจากการปรับโครงสร้างโค้ดแอปพลิเคชัน ในทางกลับกัน ผลบวกลวงจะเกิดขึ้นเมื่อการทดสอบผ่าน แม้ว่าโค้ดที่ทดสอบจะไม่ถูกต้องก็ตาม
วิธีแก้ปัญหาอย่างหนึ่งคือพิจารณาผู้ใช้ประเภทต่างๆ ที่คุณมี ผู้ใช้ปลายทางและนักพัฒนาซอฟต์แวร์อาจใช้แนวทางที่แตกต่างกัน และอาจโต้ตอบกับโค้ดต่างกัน เมื่อวางแผนการทดสอบ คุณต้องพิจารณาสิ่งที่ผู้ใช้จะเห็นหรือโต้ตอบด้วย และทําให้การทดสอบขึ้นอยู่กับสิ่งเหล่านั้นแทนรายละเอียดการติดตั้งใช้งาน
เช่น การเลือกตัวเลือกที่มีแนวโน้มที่จะเปลี่ยนแปลงน้อยลงอาจทําให้การทดสอบน่าเชื่อถือมากขึ้น เช่น data-attributes แทนตัวเลือก CSS ดูรายละเอียดเพิ่มเติมได้ที่ Kent C. บทความของ Dodds ในหัวข้อนี้ หรือติดตามบทความเกี่ยวกับหัวข้อนี้ที่จะเผยแพร่ในภายหลัง
การจำลอง: อย่าเสียการควบคุม
การจำลองเป็นแนวคิดที่กว้างๆ ซึ่งใช้ในการทดสอบหน่วยและบางครั้งใช้ในการทดสอบการผสานรวม ซึ่งเกี่ยวข้องกับการสร้างข้อมูลหรือคอมโพเนนต์จำลองเพื่อจําลองการพึ่งพาที่มีการควบคุมแอปพลิเคชันโดยสมบูรณ์ ซึ่งช่วยให้ทำการทดสอบแบบแยกได้
การใช้การจําลองในการทดสอบจะช่วยปรับปรุงการคาดการณ์ การแยกข้อกังวล และประสิทธิภาพ และหากต้องทำการทดสอบที่ต้องอาศัยการมีส่วนร่วมของมนุษย์ (เช่น การยืนยันหนังสือเดินทาง) คุณจะต้องปกปิดข้อมูลโดยใช้การจำลอง ด้วยเหตุนี้ โมคจึงถือเป็นเครื่องมือที่มีประโยชน์ที่ควรพิจารณา
ในขณะเดียวกัน การจำลองอาจส่งผลต่อความแม่นยำของการทดสอบ เนื่องจากเป็นการจำลอง ไม่ใช่ประสบการณ์การใช้งานจริงของผู้ใช้ คุณจึงต้องใช้โม็กและสตับอย่างระมัดระวัง
คุณควรจำลองในการทดสอบจากต้นทางถึงปลายทางหรือไม่
โดยทั่วไปแล้ว ไม่ได้ แต่การจำลองอาจช่วยแก้ปัญหาได้บ้างในบางครั้ง ดังนั้นเราจึงไม่ควรปิดโอกาสนี้ไปเลย
ลองจินตนาการถึงสถานการณ์นี้ คุณกำลังเขียนการทดสอบสำหรับฟีเจอร์ที่เกี่ยวข้องกับบริการของผู้ให้บริการการชำระเงินบุคคลที่สาม คุณอยู่ในสภาพแวดล้อมเสมือนจริงที่บริษัทได้จัดเตรียมไว้ ซึ่งหมายความว่าจะไม่มีธุรกรรมจริงเกิดขึ้น ขออภัย Sandbox ทำงานผิดปกติ จึงทําให้การทดสอบไม่สําเร็จ ผู้ให้บริการชำระเงินต้องเป็นผู้ดำเนินการแก้ไข สิ่งที่คุณทำได้คือรอให้ผู้ให้บริการแก้ไขปัญหา
ในกรณีนี้ การลดการพึ่งพาบริการที่คุณควบคุมไม่ได้อาจเป็นประโยชน์มากกว่า เรายังคงแนะนำให้ใช้การจำลองอย่างระมัดระวังในการทดสอบการผสานรวมหรือการทดสอบจากต้นทางถึงปลายทาง เนื่องจากจะลดระดับความเชื่อมั่นของการทดสอบ
รายละเอียดการทดสอบ: สิ่งที่ควรและไม่ควรทำ
สรุปแล้ว การทดสอบประกอบด้วยอะไรบ้าง และการทดสอบแต่ละประเภทมีความแตกต่างกันไหม มาดูรายละเอียดของบางแง่มุมที่ปรับให้เหมาะกับการทดสอบประเภทหลักกัน
องค์ประกอบของ Unit Test ที่ดีมีอะไรบ้าง
การทดสอบ 1 หน่วยที่เหมาะและมีประสิทธิภาพควรมีลักษณะดังนี้
- มุ่งเน้นที่บางแง่มุม
- ทำงานได้อย่างอิสระ
- ครอบคลุมสถานการณ์ขนาดเล็ก
- ใช้ชื่อที่สื่อความหมาย
- ทำตามรูปแบบ AAA หากมี
- รับประกันการทดสอบที่ครอบคลุม
สิ่งที่ควรทำ ✅ | สิ่งที่ไม่ควรทำ ❌ |
---|---|
ทดสอบให้น้อยที่สุด ทดสอบทีละรายการต่อกรอบการทดสอบ | เขียนการทดสอบในหน่วยขนาดใหญ่ |
แยกการทดสอบไว้เสมอและจำลองสิ่งที่คุณต้องการซึ่งอยู่นอกยูนิต | ใส่คอมโพเนนต์หรือบริการอื่นๆ |
ทดสอบแยกกัน | ใช้การทดสอบก่อนหน้านี้หรือแชร์ข้อมูลการทดสอบ |
ครอบคลุมสถานการณ์และเส้นทางต่างๆ | จำกัดการทดสอบให้อยู่ในเส้นทางที่ถูกต้องหรือทดสอบเชิงลบเป็นส่วนใหญ่ |
ใช้ชื่อการทดสอบที่สื่อความหมายเพื่อให้คุณเห็นสิ่งที่จะทดสอบได้ทันที | ทดสอบตามชื่อฟังก์ชันเท่านั้น สื่อความหมายไม่เพียงพอ testBuildFoo() หรือ testGetId() |
มุ่งเน้นที่การครอบคลุมโค้ดที่ดีหรือกรณีทดสอบที่หลากหลายมากขึ้น โดยเฉพาะในระยะนี้ | ทดสอบจากทุกคลาสไปจนถึงระดับฐานข้อมูล (I/O) |
การทดสอบการผสานรวมที่ดีควรมีลักษณะอย่างไร
การทดสอบการผสานรวมที่เหมาะสมจะมีเกณฑ์บางอย่างร่วมกับการทดสอบ 1 หน่วยด้วย อย่างไรก็ตาม ยังมีอีก 2 ประเด็นที่คุณควรพิจารณา การทดสอบการผสานรวมที่ดีควรมีลักษณะดังนี้
- จำลองการโต้ตอบระหว่างคอมโพเนนต์
- ครอบคลุมสถานการณ์ในชีวิตจริง และใช้การจําลองหรือสแต็บ
- พิจารณาประสิทธิภาพ
สิ่งที่ควรทำ ✅ | สิ่งที่ไม่ควรทำ ❌ |
---|---|
ทดสอบจุดผสานรวม: ยืนยันว่าแต่ละหน่วยทำงานร่วมกันได้อย่างราบรื่นเมื่อผสานรวมกัน | ทดสอบแต่ละหน่วยแยกกัน นั่นคือวัตถุประสงค์ของ Unit Test |
ทดสอบสถานการณ์ในชีวิตจริง: ใช้ข้อมูลทดสอบที่มาจากข้อมูลในชีวิตจริง | ใช้ข้อมูลทดสอบที่สร้างขึ้นโดยอัตโนมัติซ้ำๆ หรือข้อมูลอื่นๆ ที่ไม่ได้แสดงถึง Use Case ในชีวิตจริง |
ใช้การจําลองและสตับสําหรับทรัพยากรภายนอกเพื่อควบคุมการทดสอบที่สมบูรณ์ | สร้างการพึ่งพาบริการของบุคคลที่สาม เช่น คำขอเครือข่ายไปยังบริการภายนอก |
ใช้กิจวัตรการล้างข้อมูลก่อนและหลังการทดสอบแต่ละครั้ง | ลืมใช้มาตรการล้างข้อมูลภายในการทดสอบ ไม่เช่นนั้นอาจทําให้การทดสอบไม่สําเร็จหรือเกิดผลบวกลวงได้ เนื่องจากไม่มีการแยกการทดสอบที่เหมาะสม |
การทดสอบจากต้นทางถึงปลายทางที่ดีควรมีลักษณะอย่างไร
การทดสอบจากต้นจนจบที่ครอบคลุมควรมีลักษณะดังนี้
- จำลองการโต้ตอบของผู้ใช้
- ครอบคลุมสถานการณ์ที่สำคัญ
- ครอบคลุมหลายเลเยอร์
- จัดการการดำเนินการแบบไม่พร้อมกัน
- ยืนยันผลลัพธ์
- คำนึงถึงประสิทธิภาพ
สิ่งที่ควรทำ ✅ | สิ่งที่ไม่ควรทำ ❌ |
---|---|
ใช้ทางลัดที่ขับเคลื่อนโดย API ดูข้อมูลเพิ่มเติม | ใช้การโต้ตอบ UI สําหรับทุกขั้นตอน รวมถึงฮุก beforeEach |
ใช้กิจวัตรการล้างข้อมูลก่อนการทดสอบแต่ละครั้ง ให้ความสำคัญกับการแยกการทดสอบมากกว่าการทดสอบหน่วยและการทดสอบการผสานรวม เนื่องจากมีความเสี่ยงที่จะเกิดผลข้างเคียงมากกว่า | ลืมล้างข้อมูลหลังจากการทดสอบแต่ละครั้ง หากคุณไม่ล้างสถานะ ข้อมูล หรือผลข้างเคียงที่เหลืออยู่ สถานะ ข้อมูล หรือผลข้างเคียงเหล่านั้นจะส่งผลต่อการทดสอบอื่นๆ ที่ดำเนินการในภายหลัง |
ถือว่าการทดสอบจากต้นทางถึงปลายทางเป็นการทดสอบระบบ ซึ่งหมายความว่าคุณต้องทดสอบทั้งสแต็กแอปพลิเคชัน | ทดสอบแต่ละหน่วยแยกกัน นั่นคือวัตถุประสงค์ของ Unit Test |
ใช้การจำลองให้น้อยที่สุดหรือไม่ใช้เลยในการทดสอบ โปรดพิจารณาอย่างรอบคอบหากต้องการจำลองการพึ่งพาภายนอก | ใช้การจำลองเป็นหลัก |
พิจารณาประสิทธิภาพและปริมาณงาน เช่น ไม่ทดสอบสถานการณ์ขนาดใหญ่มากเกินไปในการทดสอบเดียวกัน | ครอบคลุมเวิร์กโฟลว์ขนาดใหญ่โดยไม่ต้องใช้แป้นพิมพ์ลัด |