TDD ไม่รู้จักหรอกเอาแค่เริ่มรู้จัก Test ก่อน

บทความนี่อยากแนะนำเกี่ยวกับอีกสกิลหนึ่งที่คนเป็นนักพัฒนาต้องพยายามเข้าใจมัน ทั้งๆที่มันค่อนข้าง abstract และงงๆสำหรับคนบางคนที่เขียนโปรแกรมมาซักพัก หลายๆคนอาจจะเคยได้ยินเรื่อง TDD ( Test Driven Development ) ซึ่งถ้าใครเคยเรียนคอร์สหรือสัมผัสมาบางจะรู้สึกว่ามัน ว้าวมาก เราจะพัฒนาโปรแกรมได้อีกเยอะแน่ๆ เอาแต่เข้าใจริงๆ คือแม่งยากมากในการเริ่มต้น ผมก็เป็นคนหนึ่งในนั้น ผมรู้สึกว่ามันเจ๋งแต่พอจะใช้งานจริงมันลำบากมากๆ เลยจะมาเขียนสอนแบบง่ายๆก่อนครับ โดยบทความนี้เรายังจะไม่เขียนเทสเขียน code นะครับเราจะเริ่มทำความเข้าใจมันก่อน

Test คืออะไร ?

การเขียนโปรแกรมเพื่อตรวจสอบโปรแกรมอีกที เช่น เราเขียนมา function หนึ่งให้บวกสองจำนวนที่โยนเข้ามาใน function นี้โดยเราจะตรวจสอบความถูกต้องว่า ถ้าโยนเข้ามามันจะไม่ลบ ไม่คูณ ไม่หาร ไม่ใช่ return string ออกมาทำนองนี้ ซึ่งความรู้พวกนี้คนอ่านส่วนใหญ่ก็บอกว่า กูก็รู้วะ ใช่ !! เอาจริงๆผมเข้าใจนะว่าตอนเราอ่านพวกความรู้มันอธิบายแบบนี้แหละ เขียน Test case มาตรวจสอบโปรแกรมที่เราเขียนแต่ความเป็นจริงคือ …

แม่งไม่เคยมีเวลาให้ฝึกเลย และทุกอย่างก็รีบๆจะเอาโปรแกรมเราเสมอ

ทำไมมันถึงสำคัญที่ควรจะฝึก

มันเป็นเสมือนคนช่วยเหลือของคุณไง ยังไง ? คือ ผมยกตัวอย่างง่ายๆนะครับ คุณเข้าไปทำงานทีมใหม่และแก้ไขโปรแกรมหนึ่งที่ส่งต่อมาหลายมือแล้ว เจ้าของธุรกิจไม่รู้ว่าสิ่งนี้แก้ไขยังไง แต่รู้แค่มันทำงานได้ เลยให้คุณแก้ไขมัน นิดหน่อยง่ายๆ เพื่อให้มันเพิ่มการรองรับการทำงานบางอย่างขึ้นมา แต่เมื่อคุณเปิดไฟล์ดูก็รับรู้เลยว่า คนก่อนๆเขียนมาแบบ แก้ไขให้ทำงานได้ไปก่อน ไม่สนใจว่ามันจะดีหรือไม่ดีแค่ทำงานได้ เปรียบเทียบง่ายๆสมมติว่า โปรแกรมมันจะทำงานโดยค่สุดท้ายจะออกมาเป็น 2 บางคนสามารถเขียนโปรแกรมให้ทำงานได้เร็วโดยการเอา 1 + 1 ก็จะได้คำตอบที่ดีและเร็ว แต่ !!!! ในโลกความเป็นจริงอันนี้คือโปรแกรมที่คุณจะเจอ

คือบางคนที่พัฒนามาก่อนอาจจะไม่ได้หาคำตอบที่ดีที่สุดของโปรแกรมสมมติตัวอย่างข้างบนได้คำตอบออกมาเป็น 2 เหมือนที่โจทย์กำหนดหรือ Business ต้องการ แต่คนมาแก้ไขทีหลังจะทำหน้าอย่างไร ? บางคนก็อาจจะอวยพรถึงคนก่อนรัวๆ และเมื่อคุณเข้าไปแก้ไขไอ้สิ่งที่ Business บอกว่า ง่ายๆทำแปปเดียวเสร็จ ผลลัพธ์มักจะเป็นอย่างนี้

http://imgur.com/gallery/hsN5Mgi

แต่มันจะดีกว่าถ้ามีคนก่อนเขียน เทสไว้หรือคุณเขียนเทสทดสอบโปรแกรมก่อนที่จะลงมือทำอะไรลงไป อย่างน้อยๆก็ยังมี save point ว่าถ้าเราเปลี่ยนอะไรซักอย่างใน function มันจะไม่พินาศ และเรายังสามารถ optimize code เราได้อีกด้วยโดยเราไม่กลัวว่าการที่เราปรับเปลี่ยน code นั้นจะไม่ทำให้ระบบพังโดยเมื่อเราแก้ไขเสร็จก็จะรัน Test เพื่อให้ทราบว่าผลของการเปลี่ยนมันกระทบไหม แรกๆเราเขียนอาจจะมีการเชื่อมโยงน้อย เช่น การเปลี่ยนแปลงตรงนี้ถ้าส่งค่าผิดเราอาจจะยังตามได้ แต่ถ้าหากมันกระทบกับระบบอื่นหรือ code ชุดเก่าที่ถ้าส่งค่าผิดมันอาจจะไม่ทำงาน พวกนี้ถ้าเรามี เทส รันแบบง่ายๆก็ยังดีให้เรารู้

แล้วจะเริ่มต้นยังไง ?

อย่างแรกสุดที่ต้องเตรียมเลยคือ การรู้ว่าอะไรที่ควรจะเข้าไปเทส ไม่ใช่มาถึงลงมือเขียนเลย ผมจะยกตัวอย่างแล้วกันครับ สมมติ function ที่เราจะเข้าไปแก้ไขเป็น function login ฟังดูใครๆก็น่าจะมี function นี้ถูกต้องไหมครับใน function นี้เขียนประมาณนี้ ภาษา PHP นะครับ

จากตัวอย่างที่กำหนดมาให้คุณเห็นจะเทสยังไงครับ ? ใน function login มันดันประกอบไปด้วย function ย่อยๆ 4 function ได้แก่ sanitizeInputReturnArray , checkLogin, redirect, redirectLoginFromAndNoticeError ซึ่งเราต้องเทสทั้งสี่อันนี้ก่อนถึงจะบอกได้ว่าตัว Login function นี้จะออกมาแบบไหนอย่างไร ถูกต้องหรือไม่

อย่างแรกให้เราเข้าไปดู code ของ sanitizeInputReturnArray function ก่อนว่ามันทำงานอย่างไร โยนเข้าไปสองค่าแล้วเกิดอะไรขึ้นบ้าง ถ้าสมมติในนี้มันเขียนอะไรอีกที่มันเยอะเยะ ก็ต้องค่อยๆไล่ดูว่เราจะไปเทสที่จุดไหนก่อนสำคัญคือ คุณต้องดูว่าจะไปเริ่มในส่วนย่อยตรงไหน สมมติว่าตัว function ทำจบในตัวเองโยนเข้ามาสองค่าและ return เป็น array ไป และมันทำการ remove พวก input แปลกๆออกพวก specialchar พวกมี qoute , double qoute , @ อะไรพวกนี้เราก็สามารถเริ่มจาก function นี้ได้ครับ

สังเกตุและสมมติ Test case

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

เอาจริงๆผมเขียน test ใน node.js มันง่ายกว่า PHP นะครับ ถ้าอย่างไรบทความหน้าผมจะเขียนเป็น node.js แล้วกันนะครับ ดังรูปด้านบน เราจะทำการ test แค่ function ที่เราต้องแยกออกมา เพื่อจะเช็คดูว่าแต่ละตัวต้องการค่าแบบไหน และ return ที่ออกมาเป็นอย่างไร พอเห็นภาพไหมครับ ?

เมื่อเราเห็นแล้วว่า function มันโยนสองค่าเราจะสามารถคิด test case ได้หลายอย่างได้เช่น ถ้าเราโยนไปค่าเดียวจะ error ไหม อย่างนี้ก็คือ 1 test case แล้ว หรือถ้า function รับค่าเป็น string เราส่งเป็นตัวเลขได้ไหม เป็นต้น ก็จะมีคำถามว่าแล้วต้อง test case เท่าไร คำตอบคือ แล้วแต่ความสำคัญของ function ครับเช่น ถ้าหาก login พังมันยังอาจจะยังไม่สำคัญเท่ากับ function การคำนวน เงินครับ

ติดตาม Test ตอนหน้านะครับ