5 เหตุผลที่ช่วยบอกคุณได้ว่าทำไม Test ของคุณถึง Flaky

Traitanit Huangsri
LINE Developers Thailand
3 min readNov 7, 2018

สวัสดีครับ ผมว่าคงจะมีหลายๆ คนที่เคยเจอปัญหาเดียวกันกับผมว่าทำไม Automated Test ที่เราเขียนนั้นมันช่าง Flaky เหลือเกิน จะแก้ปัญหายังไงดี วันนี้ผมมี 5 เหตุผลที่จะช่วยคุณบอกได้ว่า สาเหตุที่ Test ของคุณนั้น Flaky เกิดขึ้นมาจากอะไรได้บ้าง

แต่ก่อนอื่นเรามาทำความเข้าใจกันก่อนว่า คำว่า Flaky Test นั้นคืออะไร มันหมายถึงอะไรกันแน่

คำว่า Flaky Test ในเชิง Software Development นั้นมีความหมายว่า Test ที่ไม่น่าเชื่อถือ (Unreliable Test) นั่นเองครับ กล่าวคือ Test ที่ให้ผล Test ไม่เหมือนกันในการรันแต่ละครั้ง บางครั้งก็อาจจะรันผ่าน บางครั้งก็รันไม่ผ่าน โดยที่ไม่ได้แก้โค้ด Application แต่อย่างใด ซึ่งเป็นปัญหาใหญ่ระดับชาติที่หลายๆ องค์กรก็เจอปัญหานี้เช่นกัน ขนาด Tech Company ใหญ่ๆ ระดับโลกอย่าง Google ก็เคยเจอปัญหานี้นะครับ

หลายคนที่อุตส่าห์ลงทุนเขียน Automated Test เพื่อหวังว่าให้มันช่วยลดภาระ (Effort) ในการทำ Manual Test ก็คงรู้สึกว่าการที่มี Flaky Test นั้นเป็นปัญหาใหญ่ที่ต้องการแก้ไขอย่างเร่งด่วน เพราะแทนที่มันจะช่วยให้เราทำงานได้เร็วขึ้น มีประสิทธิภาพมากขึ้น กลับกลายเป็นงานเพิ่มที่เราต้องคอยแก้ไขจุดที่มัน Flaky ให้มันใช้งานได้อยู่บ่อยๆ

ประเด็นก็คือ Flaky Test มันเกิดขึ้นได้จากอะไรบ้างล่ะ? มาดูกันครับ

1. การแบ่ง Test Level ที่ไม่เหมาะสม

ตามหลักการทำ Test ที่ดีแล้วนั้น เราควรแบ่งการ Test Level ของเราให้เหมาะสมตาม Concept Test Pyramid ตามรูปครับ

Credit: https://www.ministryoftesting.com/dojo/lessons/the-mobile-test-pyramid

ผมเชื่อว่ายังมีหลายๆ คนที่ยังติดอยู่กับการทำ Test ในระดับ End-To-End (E2E) Tests ในปริมาณมากๆ ซึ่งมีข้อเสียหลายอย่าง ยกตัวอย่างเช่น

  • Test ใช้เวลาในการรันนาน เพราะต้อง Test ในมุมมองของ User Perspective แบบ Black Box Testing จริงๆ และส่วนใหญ่เป็นการทำ UI Testing
  • Test ต้องการ Dependency สูง เช่นต้องมี Server-Side (Backend) ที่พร้อมให้บริการตลอดเวลา, Database ต้องไม่มีใครไปแก้ไขข้อมูลใดๆ ซึ่งในการทำ Software Development บ่อยครั้งที่ Backend และ Frontend ต้องมีการพัฒนาไปพร้อมๆ กันก็มักจะเกิดปัญหาเรื่อง Dependency Issue นี้เสมอครับ

เพราะฉะนั้น การแบ่ง Test Level ที่เหมาะสมนั้นจะช่วยให้เรา Focus กับ Feature ที่เราต้องการจะTestได้อย่างถูกจุด เราควรให้ความสำคัญกับ Unit Test ให้มากๆ และลดปริมาณของ End-To-End Test ให้น้อยลง เหลือแค่เฉพาะ Critical Path ที่มี User ใช้งานเยอะๆ หรือเป็น Feature ที่ต้องการันตี Functionality ให้ทำงานถูกต้องเสมอก็พอแล้ว ซึ่งสัดส่วนของ Test Level จาก ​Unit/Integration/E2E ควรจะเป็น 70:20:10 ครับ (Reference ตามสัดส่วนของ Google แนะนำนะครับ) ซึ่งถ้าเรายิ่งทำ Test Low Level มากเท่าไร โอกาสที่จะเกิด Flaky Test ก็จะน้อยลงเท่านั้นครับ (และTestก็จะยิ่งรันเร็วมากขึ้นด้วยครับ)

2. 3rd Party Dependencies

ปัญหานี้เป็นปัญหา Classic ที่หลายๆ คนน่าจะเคยเจอกัน ก็คือ Application ของเรามี Dependency กับ 3rd Party Application ที่เราควบคุมไม่ได้ ซึ่งถ้า 3rd Party Application มีการเปลี่ยนแปลงหรือกำลังอยู่ในช่วงพัฒนาไปพร้อมๆ กับ Application ที่เราต้องการจะTest เช่นกรณีของ Backend/FrontEnd ที่พูดถึงก่อนหน้านี้ ก็จะทำให้เกิดปัญหา Flaky Test อย่างแน่นอนครับ รับประกันได้เลย ทางแก้ทางเดียวคือเราต้องนำ Concept ของการทำ Dependency Injection (DI) เช่นการ ​Mock/Stub/Spy เข้ามาช่วยตัด Dependency ที่ไม่เกี่ยวข้องกับ Application ของเราออกไปให้ได้มากที่สุด ตัวอย่างเช่น Network Requests , Data Storage/Caching Layer ต่างๆ ซึ่งก็จะส่งผลดีให้เราสามารถ Control ปัจจัยทุกอย่างที่จะทำให้เกิด Flaky Test ได้ครับ

3. Large Test

การเขียน Test ที่มีขนาดใหญ่จนเกินไป มีผลทำให้เกิด Flaky Test ด้วยครับ เช่นการเขียน Test เป็น Flow ยาวๆ เยอะๆ (End-To-End Test) ก็จะทำให้ Test Case 1 ข้อมี Step ในการ Test ที่ยาวมากเกินไป ซึ่งยิ่งพอมี Step มากขึ้นก็จะยิ่งมีโอกาส Flaky มากขึ้นไปด้วยครับ วิธีการแก้ไขคือเราต้องเขียน Test ให้มีขนาดเล็กลง (Small Test) ลดการทำ Setup Step ต่างๆ ให้น้อยลง หันไปใช้ Dependency Injection ให้มากขึ้น ทำ Test ในจุดที่ควรจะต้อง Test จริงๆ ไม่เขียน Test 1 ข้อเพื่อ Test ทุกอย่าง (Test 1 ข้อควรจะมี Objective ที่ชัดเจนว่าต้องการจะ Test อะไรแค่ 1 อย่าง)

4. Infrastructure Problem

หลายคนอาจจะเคยเจอปัญหาว่าทำไมเขียนและรันTestในเครื่องตัวเองแล้วผ่านตลอด แต่ทำไมพอไปรันบน Continuous Integration System แล้วพังตลอด ปัญหานี้เกิดจาก Environment Configuration เช่น Operating System, Software/Library Version ที่แตกต่างกันระหว่าง Development Environment กับ CI Environment ครับ วิธีการแก้ไขอย่างนึงก็คือการนำ Containerize Platform มาใช้งาน เช่น Docker มาช่วยให้เราการรันตีได้ว่า Environment ที่เราใช้เขียนโค้ด Test คือ Environment แบบเดียวกันที่เราเอา Test ของเราขึ้นไปรันบน CI นั่นเองครับ

5. Test Framework

Test Framework เป็นสิ่งนึงที่ทำให้เกิด Flaky Test ได้เชื่อไหมครับ? การเลือก Test Framework ที่ไม่เหมาะสมกับ Application ของเรา ก็เป็นสิ่งนึงที่ทำให้เกิด Flaky Test ได้ครับ ยกตัวอย่างเช่น บางคนที่ต้องการทำ API Test แต่ไปเขียนเป็น Web Interface มาครอบอีกชั้นเพื่อให้ทำ API Call ง่ายๆ ผ่านการกดปุ่มๆแล้วใช้ Web Test Framework มาทำเทส แบบนี้ไม่ค่อยเหมาะครับ ควรจะใช้ API Test Framework โดยตรงไปเลยดีกว่า

Test Framework ที่ดีควรจะต้องมี Feature หรือ Tool ที่จะช่วยทำให้ Test ของเรารันได้อย่าง Stable เช่นรองรับการทำ Dependency Injection ได้ด้วยตัว Test Framework เอง, สามารถเข้าถึง Objects, State ของ Application ของเราในตอน Run Time ได้ เพื่อให้เราสามารถทำTestได้ในระดับ Low Level มากขึ้น, และมีความสามารถในการทำ Debugging ที่ดี เพื่อช่วยให้คนเขียนTestสามารถ Investigate ปัญหาที่เกิดขึ้นเมื่อ Test Fail ได้ง่ายๆ ด้วยครับ

สรุป

สุดท้ายสิ่งที่สำคัญที่สุดก็คือคนเขียน Test ครับ คนเขียน Test ควรจะต้องมีความเข้าใจหลักการทำงานและโครงสร้างของ Application ที่ต้องการจะ Test เป็นอย่างดี มีการ Design การเขียน Test ที่ดี บอกได้ว่าสิ่งไหนควรหรือไม่ควรต้องเขียน Test ถ้าจะเขียนควรจะเขียน Test ใน Level ไหน

การเขียน Test Code มันก็เหมือนเป็นการทำ Software Development แบบหนึ่งครับ ซึ่งถ้าเราปฏิบัติกับ Test Code ให้เหมือนตอนเราเขียน Application Code ยกตัวอย่างเช่นการนำ Practice ต่างๆ ตอนเราเขียน Application Code มาใช้ เช่นการทำ Code Review, Design Pattern ต่างๆ ก็เป็นสิ่งที่จะช่วยทำให้ Test ของเรามี Quality มากยิ่งขึ้นได้ด้วยครับ

--

--