เกรยนเพรส
2010
มาท า TDD กนเถดดวย NUnit
Translator is someone using @olarn_?
_Early_Access_Program_
?
บทท 1 - INTRODUCTION
การทดสอบซอฟทแวรนนมมากมายหลายวธบางวธตองอาศยความรวมมอจาก end-user ในขณะทบางวธตองอาศยทกษะของคนทอยในฝาย Quality Assurance (หรอ QA) เขามาชวยดวย หรอบางวธกตองใชเครองมอส าหรบการท า เทสทing เฉพาะทางทมราคาแพง แตนนไมใชสงทเราจะพดถงกนเราก าลงพดถงสงทเรยกวา ยนท เทสทing แลวมนคออะไร??? อยาเพงสงสยวามนคออะไรมารกนกอนวามนเปนสวนส าคญทชวยท าใหโครงการประสบความส าเรจ ท าใหงานมคณภาพและทส าคญการท า ยนท เทสทing นนไมจ าเปนตองมคาใชจายอะไรมากมาย แตกลบชวยให โคด ทไดมคณภาพ และยงชวยใหการพฒนาเปนไปอยางรวดเรวอกดวย วเศษ “ยนท เทสทing” เปนวธการทดสอบการท างานของ โคด ดวยการเขยน โคด สนๆ ขนมาเพอทดสอบ โคด ของเราเอง ซงในหนงสอเลมนจะใช framework ส าหรบการทดสอบ โคด ทเรยกวา Nยนท โดยปกตแลวในหลายๆ หนวยงาน บรษท หรอองคกร จะใหความส าคญกบการทดสอบเปนอยางมาก โดยเฉพาะเมอการพฒนาถงขนตอนของการทดสอบระบบแตการทดสอบแบบนนเปนการทดสอบ ทเกดขนในชวงปลายของโครงการ ปญหากคอถาระยะเวลาทจะตองสงมอบกระชนเขามาจนไมสามารถทดสอบไดทน การทดสอบบางสวนมกถกท าอยางไมตงใจหรอไมอาจรายแรงขนาดการทดสอบทงหมดกจะถกยกเลกไป เพอใหสงมอบระบบทนตามระยะเวลาทก าหนด ส าหรบโปรแกรมเมอรสวนใหญนนมกจะรสกโดยธรรมชาตวาการทดสอบนนนาร าคาญและมกจะไมอยากท ามน โดยทคนเหลานนมกคดวานาจะเอาเวลาทจะตองใชในการทดสอบนน ไปพฒนาโคดทตวเองจะตองท าดกวา ในขณะททกคนตางกเหนดวยวาการทดสอบนนส าคญ เหมอนกบททกคนเหนดวยวา เพอสขภาพทดแลว กควรทจะกนผกใหมากๆ เลกสบบหร พกผอนใหเพยงพอ และออกก าลงกายอยางสม าเสมอ แตนนกไมไดหมายความวาทกคนทเหนดวยจะท าตามนน ในความเปนจรงแลว ยนท เทสทing เปนอะไรทมากกวานน คณอาจจะคดวา ยนท เทสทing นน มนกเหมอนกบการพยายามกนผกใหมากขน แตเราอยากจะบอกวา ยนท เทสทing มนเหมอนกบการใสเครองปรงรสลงไปในอาหารเพอใหมรสชาดทอรอยขนมากกวา ซง ยนท เทสท ไมไดถกคดขนมาเพอตอบสนองความตองการเชงคณภาพในฝงธรกจ มนไมใชเครองมอของ end-user หรอของ manager หรอแมแตส าหรบหวหนาทม แต ยนท เทสท นนถกพฒนาโดยโปรแกรมเมอร มไวส าหรบโปรแกรมเมอร และเพอประโยชนของโปรแกรมเมอรเทานน เพอท าใหโปรแกรมเมอรอยางเราๆ มชวตทดขนนนเองพดงายๆ ดวย ยนท เทสท อยางเดยว กสามารถท าใหเหนความแตกตาง ระหวางความส าเรจ และความลมเหลวไดเลยทเดยว ลองดตวอยางจากเรองเหลานกน
1.1 เขยน โคด อยางมนใจ
กาลครงหนงนานมาแลว … อาจจะเปนวนองคารทผานมา … มโปรแกรมเมอรสองคน ชอ แพท กบ เดล ทงสองคนก าลงท างานเพอใหทนก าหนดสงงานทใกลเขามาแพทนนเขยน โคด เรวมาก class แลว class เลา meethod แลว method เลา... จะหยดกเพยงเพอ compile โคด เทานน เพยงเพอใหแนใจวา โคด เหลานน compile ผาน แพทท างานในลกษณะนจนกระทง
ถงคนกอนวนทจะถงก าหนดสงงาน เมอถงเวลาทจะตองแสดงตวอยาง การท างานของ โคด เหลานน แพทก run โปรแกรม
ตงแตตน แตโปรแกรมไมแสดงผลลพธ อะไรออกมาเลย ไมมอะไรทงนน …แพทจงใช debugger เพอไล track ขนตอน
การท างานของ โคด … แลวแพทกพบวา “...ไอ variable ตวนมนไมควรจะเปน 0 ไดนนา...” แพทจงพยายาม track
กลบไปยงทมาทเรยก โคด จดนนเพอพยายามแกปญหา ถงตอนนมนกเลยเวลาก าหนดสงงานไปแลว bug ถกพบและแกไข
แตแพทกยงเจอ bug ตวอนในระหวางนนอก และโปรแกรมกยงไมแสดง output ออกมาอยด แพทไมเขาใจวาท าไม และคดวามนไมนาจะเปนแบบนนไปได ในขณะทเดลเขยน โคด ไมเรวนก เดลจะเขยน โคด ใหมโดยเขยน โคด ส าหรบ เทสท สนๆ ควบคกนไปเสมอ ไมมอะไรพเศษ
แคเขยน โคด เพอตรวจสอบวาท โคด ของ routine ทก าลงเขยนอยนนสามารถแสดงผลลพธออกมาไดถกตองอยางทมนควรจะเปนหรอไม มนดเหมอนกบวาเดลตองใชเวลามากกวาทจะตองคดเรอง เทสท กอน แลวจงเขยน โคด และเดลจะไมยอม
เขยนโคดของสวนอนจนกวา โคด ของ routine นนจะท างานไดอยางถกตองตาม เทสท ทเดลเขยนเอาไว
สงมหศจรรยทเกดกบเดลคอเดลแทบไมไดใช debugger เลย ตางกบแพททตอนนเหมอนก าลงพยายามแกเกมสปรศนาอย
กมหนาลงจนหวแทบจะกมตดกบมอ ท าเสยงค ารามเหมอนปศาจ กนดาเครองคอมฯ จองไปทหนาตาง debugger และท าหนาเหมอนจะกนเลอดกนเนอใครสกคนใหได
ในทสด แพทกสงงานไมทนเมอเวลาทก าหนดใหสงงานผานพนไป ในขณะท โคด ของเดลถกน าไป integrate และสวน
ใหญไมมปญหา (เพราะเดลไดทดลอง integrate โคด ตลอดเวลาอยแลวดวย ยนท เทสท) กมบางท โคด ของเดลจะมจดผดพลาด แตมนกไมยากส าหรบเดลทจะบอกวามนเกดปญหาทจดไหน เดลสามารถแกไขไดในเวลาเพยงไมกนาท มาถงจดส าคญของเรองแลว เดลกบแพทอายงานเทากน มทกษะการเขยน โคด ใกลเคยงกน สงทแตกตางกนกคอเดลนนเชอ
ใน ยนท เทสทing และ เทสท ทกครงทม method ใหมกอนทจะให โคด ในสวนอนๆ จะไดเรยกใชมน แพทไมท าแบบนน
แพท “คดเอาเอง” วา โคด นาจะ work อยางทเขยนมนถกเขยนขนมา และไมยอมเสยเวลาทจะลองทดสอบจนกระทง โคด
ทงหมดเกอบจะเสรจแลว ซงนนกสายเกนไป และมนกยากทจะหาวา bug นนมาจากสวนไหนของ โคด แมแตจะบอกวา สวน
ไหนของ โคด ทท างานไดบาง และสวนไหนทไม work กยงยากเลย
1.2 ยนท เทสทING คออะไร
ยนท เทสท เปนชนสวนของ โคด เลกๆ ทเขยนโดยโปรแกรมเมอรเอง และเขยนขนมาเพอทดสอบเฉพาะ ฟงกชน หนงๆ เทานน
โดยทวไปเราจะเขยน ยนท เทสท เพอทดสอบแตละ method ส าหรบเรองๆ หนง ตวอยางเชน คณอาจจะเขยน โคด เพอ
sort ขอมลขนาดใหญ และเขยน ยนท เทสท เพอตรวจสอบวา ผลลพธนนเรยงกนถกตอง หรอเขยน ยนท เทสท เพอทดสอบ
ใหมนใจวาเมอลบตวอกษรตวหนงออกจาก string แลว ตวอกษรนนมนตองหายไปจรงๆ
ยนท เทสทing มไวเพอพสจนวา โคด แตละชนนน ท างานถกตองตามทนกพฒนาตงใจทจะ ใหมนท างานแบบนนจรงๆ
ในขณะทท า ยนท เทสท เราไมจ าเปนตองไปค านงวา โคด ทเขยนนนเปนไปตาม requirement ท end-user ตองการ
หรอไม นนเปนเรองของการท า acceptance เทสท, การ validation, verification และการแกไข
(correctness) ใหตรงตาม requirement ซงมนยงไมถงเวลาทจะท าในตอนน แมแตเรองของ performance
กยงไมจ าเปนตองคดถง สงทเราตองท า ณ เวลานกคอพสจนใหไดวา โคด เหลานนสามารถท างานไดถกตองอยางทมนควรจะ
เปน (แนนอนวาเราตองรวา สงทควรจะเปนนนคออะไร) เพราะฉะนนเราจงตองท าการทดสอบไปทละ ฟงกชน และท าใหมนใจวาแตละ ฟงกชน นน ท างานอยางทควรจะเปนจรงๆ จากนนจงคอยน าทกอยางมารวมกน แลว เทสท ทงระบบอกครง
อาจจะพดไดวา ถาเราพดไดไมเตมปาก วา โคด ทเราเขยนขนมานนจะสามารถท างานไดจรง ตามทเราตงใจไวหรอไมแลวละก
การทดสอบแบบอนกไมตองเสยเวลาพดถงอก แนนอนวาการทดสอบอนๆ นนยงคงจ าเปนอย (ขนอยกบระบบทก าลงพฒนา
การทดสอบอนๆ อาจจ าเปนมากกวาการทดสอบดวย ยนท เทสท ดวยซ า) แตการทดสอบในระดบ source โคด นนตองท ากอน
เสมอ
1.3 ท าไมตองเสยเวลากบ ยนท เทสทING?
ตอบงายๆ ยนท เทสทing จะชวยใหชวตของเรางายขน นนคอเหตผลวาท าไมเราก าลงอานหนงสอเลมน ยนท เทสทing จะ
ชวยให design ของคณดขนกวาเดมและลดเวลาในการแก bug ลงอยางฮวบฮาบ เรารวาโปรแกรมเมอรชอบเขยน โคด แต
เวลาทเสยไปในการแก bug นน มนเปนชวงเวลาทสญเปลา เพราะเราจะไมไดเขยน โคด เลย แตก าลงเสยเวลาโดยเปลาประโยชนไปกบการแก โคด เกาตางหาก
จากเรองราวในหวขอทแลว แพทมปญหาเพราะคดไปเองวา โคด ในระดบลาง (low-level) จะท างานไดอยางถกตอง แตเมอน ามนมาท างานรวมกบ โคด ในระดบบนกลบเกดปญหาขนมา ซงมนกเหมอนกบการเอาไพมาประกอบเปนบาน แตโครงสรางของไพใบลางๆ ไมมนคง มนจงพงลงมาทงหลงเมอตองน าไปประกอบกบสวนทอยดานบนนนเอง เชนเดยวกน เมอ
โคด ในระดบ low-level มปญหา และคณพยายามทจะแกปญหานนโดยทไมมอะไรรองรบ โอกาสท โคด นนจะไปกระทบ
กบ โคด ในสวน high-level กจะมมาก และนนจะยงท าใหปญหาซบซอนมากขนกวาเดม การแกกจะยากขนเปนเงาตามตว
จากเรองทเลามา แพทจะคอยพดอยเสมอวา “มนเปนไปไมได” หรอ “ผมไมเขาใจวามนเกดขนไดยงไง” ถาคณพบวาคณก าลงคดแบบนอยละก มนเปนตวบงชทชดเจนวาคณไมมความมนใจใน โคด ของคณวามนสามารถท างานไดตามทควรจะเปนหรอไมในกรณทตองการเพมความมนใจใน โคด เหมอนกรณของเดล คณตองถามไปท โคด เองวา มนก าลงท าอะไร และคอยตรวจสอบผลลพธวามนตรงตามทคณตองการใหมนเปนหรอไม ความมนใจของเดลไมไดมาจากทเดลเขาใจวา โคด ของตนเองเปนอยางไร แตมาจากความจรงทวาเดลม ยนท เทสท ทคอยตรวจสอบสงตางๆ วา โคด จะยงคงท างานไดตามทเดลคาดหวง
เสมอ เราสามารถอธบายหวใจของ ยนท เทสท ไดงายๆ วา ยนท เทสทing เปนเทคนคทดทสดเทคนคเดยว ทจะชวยใหคณเขยน โคด ไดดขน
1.4 ตองมอะไรจงจะท าแบบนนได
มนงายมากทจะน า ยนท เทสท มาใชเพราะการเขยน โคด ส าหรบ เทสท ดวยความมนใจทละนอยๆ นนมนสนก แตสดทาย
แลวเรายงคงตองเขยน โคด เพอพฒนาซอฟทแวรใหลกคาและ end-user ของเราอยด เพราะฉะนน ขอใหเขาใจจดประสงค
ของ ยนท เทสทing อกครงวา การน า ยนท เทสทing มาใช กเพราะเราตองการท าใหชวตของพวกเรา เหลาโปรแกรมเมอรมชวตทดขน รวมไปถงสมาชกคนอนๆ ในทมพฒนาใหมชวตเปนไปในทางทดขนดวย
การเขยน ยนท เทสทing ยงเปรยบเสมอนเปนการพฒนาเอกสารทสามารถน าไป execute ได ซงไมเหมอนกบการเขยน
เอกสารปกต เพราะ ยนท เทสทing สามารถตรวจสอบความถกตองของ โคด ได และมนจะตดไปกบ โคด ของเราเสมอไม
หายไปไหน (นอกจากจะลบมนทงไป) และทางทดทสดทจะพฒนาเอกสารท execute ไดโดยไมตองลงแรงมากนก กคอท า
มนตงแตตนพรอมๆ กบการเขยน production โคด นนเอง
มนท าให โคด เปนไปอยางทเราตองการรเปลา?
ทจรงแลว ขอนตองถามวา “โคด มนเตมเตมความตองการของฉนรเปลา?” เพราะ โคด ทเขยนขนมาอาจจะท าคนละเรองกบ
สงทระบไวใน requirement กได แตนนเปนคนละเรองกบการเขยน ยนท เทสทing เพราะนนเปนเรองของการไดมาซง
requirement ทถกตองและ implement ใหถกตองตาม requirement แต ยนท เทสทing จะเปนเครองมอทชวยพสจนวา โคด ทเราเขยนขนมานน สามารถท างานไดอยางถกตองตามทเราตงใจไว
แลวมนท างานตามทฉนตองการตลอดเวลาเสมอๆ รเปลา?
นกพฒนาสวนมากมกจะทดสอบแคกรณเดยว คอเฉพาะทางทถก หรอ “happy path” เทานน ซงการทดสอบแบบนนน ทกอยางดเหมอนจะสมบรณแบบแตแนนอนวาในชวตจรงนนไมมอะไรทสมบรณแบบ อะไรกเกดขนไดเสมอ เชน ม
exception ถก throw ออกมาจากระบบ, disk เตม, network มปญหา, buffer overflow หรอเพราะเรา
เขยน bug ลงไปใน โคด เอง ซงการปองกนปญหารทคาดไมถงนน คอสวนทเปน “วศวกรรม” ในการพฒนาซอฟทแวร ในกรณของการสรางสะพานดวยวศวกรรมสมยใหมนน วศวกรจะตองค านงถงการรบแรงเมอสรางสะพาน จะตองค านงถงความเรวลมเมอสะพานมความสงมากๆ ตองค านงถงการเกดแผนดนไหว หรอน าทวม เปนตน แมแตชนสวนตางๆ ทน ามาสรางสะพานกอาจจะเปนสาเหตทท าใหเกดปญหาไดเชนกน
ในการทดสอบ เราไมไดทดสอบสะพานเพยงแคการขบรถขนไปบนสะพานคนเดยวบนชองกลาง ของถนนทวางเปลาในวนทเงยบสงบ นนไมเพยงพอทจะน าไปใชงานจรงได สมมตวาเราทดสอบสะพานเพยงแคนนแลวมนสามารถใชงานไดอยางไมมปญหา กไมไดหมายความวา เราไดมการออกแบบไวเปนอยางด แตเปนเพราะมนบงเอญไมมปญหาเทานน ไมไดเปนเพราะวาเราทดสอบแลวมนจงไมมปญหา เพราะฉะนน นอกจากทเราจะตองทดสอบเพอใหมนใจวา โคด ของเราสามารถท างานไดตามทเราตองการแลว เรายงตองทดสอบเพอใหมนใจไดวา ระบบจะยงคงท างานอยได แมวาจะเกดปญหาอนๆ ตามมาดวย
แลวเราจะไวใจมนไดไหม?
โคด ทเราไมสามารถไวใจไดกไมนาจะเปน โคดทมประโยชน และยงแยไปกวานน โคด ทเรา ”คดวา” มนนาจะไวใจได (แตดน
ม bug) นนจะยงท าใหเราเสยเวลาเพอแก bug อกดวย เพราะฉะนน ถาเราตองการจะหลกเลยงเหตการณในลกษณะ
“เดนหนา 1 กาวแตถอยหลง 2 กาว” แลวละก ท า ยนท เทสท ในทกจดเพอจะไดไมตองกลบมาเสยเวลากบมนอก
ไมมใครทเขยน โคด แลวมนจะสมบรณแบบ ขอเพยงแคคณรวาปญหานนอยทไหนกพอ เราสามารถหลกเลยงปญหาไดดวย
การรวา อะไรคอขอจ ากดของ software ตวอยางเชน สมมตวาคณเขยน โคด เพอรบคาของ list ของตวเลข เมอท าการ
ทดสอบ คณพบวาโปรแกรมเกด error เมอใส empty list เขาไป แนนอนวา requirement จะไมมสวนไหนทบอก
วาคณตองรองรบ empty list ดวยนะ แตตอนนคณกรแลววา ขอจ ากดของโปรแกรมคอไมสามารถรบ empty list ได
นนคอขอจ ากดลางสด ตอไปกตองทดสอบกบขอจ ากดสงสด เชน คาของ list สงสดทโปรแกรมจะรบได เปนตน
มนเปนเอกสารทบอกวาเราตงใจจะท าอะไรรเปลา?
ผลพลอยไดอกอยางหนงของ ยนท เทสทing กคอ มนชวยสอสารวาเราตงใจเขยน โคด เพอใหมนท าอะไร นนคอ ยนท เทสท
จะท าหนาทเหมอนเอกสารทสามารถ execute ได และแสดงใหคนอนเหนวาเราตงใจจะให โคด นนท างานยงไงภายใต
เงอนไขตางๆ อยางไร สมาชกในทม (ทงในปจจบนและสมาชกใหมในอนาคต) จะใช ยนท เทสท เพอท าความเขาใจ และใชเปนตวอยางในการเรยกใช โคด ของเราได และถามใครบางคนเกดเรยกใช โคด ในแบบทเราไมไดคดถง เคาสามารถเตอนเรา
ไดทนทเพราะ โคด รปแบบนนไมมอยใน ยนท เทสท ทเราเขยนเอาไวนนเองและแนนอนวา เอกสารทสามารถ execute ไดนนมประโยชนเพอท าให โคด ถกตอง ไมเหมอนกบการเขยนเอกสารทวไป เพราะมนจะอยคกบ โคด ของเราเสมอไมหายไปไหน
1.5 เราจะท า ยนท เทสทING ไดยงไง?
เราสามารถเรยนรและน า ยนท เทสทing ไปใชไดไมยาก ซงโดยทวไปกจะมแนวทางปฎบตและขนตอน ใหคณสามารถท าตามไดงายๆ และมประสทธภาพ ดงน
ขนตอนแรกกคอ กอนทเราจะเขยน method หนงๆ เราจะตองตงโจทยขนมาวาเราคาดหวงจะไดอะไรจาก method นน
จากนนจงเขยน โคด ส าหรบ เทสท แลวจงคอยเขยน โคด ใน method นนเพอตอบโจทย ของค าถามทตงไวในตอนแรก
คณอาจจะเขยน โคด ใน method กอน จากนนจงคอยเขยน ยนท เทสท เพอ เทสท โคดกได แตคณจะพบวาการท าวธน
สงผลใหตอง refactor โคดบอยกวาวธการเขยน ยนท เทสท กอนเพราะคณตองคอยแกโคด เพอใหมนสามารถ เทสท ไดอยเรอยนนเอง
ขนตอนตอไป ท าการ run ยนท เทสท ซงอาจจะ run เปนบางสวนหรอทงหมดเทาทมกได สงทส าคญกคอ “เทสท ทงหมด
จะตองผาน” ไมใชผานเฉพาะ ยนท เทสท ทเพมเขาไปใหมเทานน ซงนนเปนพนฐานของการท า regressive เทสท เพอเปนหลกประกนวาโคดใหมไมไดไปกระทบกบ โคด เดมจนท าใหเกดปญหาขนเพราะถาเกดปญหา ยนท เทสท ของเดมทมอย
จะฟองทนทท run เทสท ไมผาน
ในทกๆ เทสท นนจ าเปนจะตองมกลไกทคอยบอกวา เทสท ตวนนผานหรอไมผาน เราจะไมถอวา เทสท ขอนนผานเพยงเพราะ
มนแสดงผลลพธออกมาไดอยางถกตอง แตจะตองเปนการตรวจสอบจาก ยนท เทสท เองเทานน ซงเราจะใช โคด “Assert”
เพอทดสอบมน เราจะพดถงรายละเอยดอกครงเมอเราน า เทสท framework มาใช
1.6 ค าแกตวเพอหลกเลยงการ เทสท
ถงแมวาสงทกลาวมาตงแตตนนนจะฟงดมเหตผลและนาสนใจกตามแตกยงมนกพฒนาอกหลายคนทแมวาจะเหนดวยแตกยง
คดวามนคงเปนไปไมไดดวยสาเหตใดสาเหตหนง ตวอยางตอไปน มกจะถกยกขนมาเปนขออางทจะไมท า ยนท เทสทing
มนเสยเวลาทจะตองเขยน เทสท
นเปนขออางยอดนยมของคนเพงรจก ยนท เทสทing ซงมนไมเปนความจรง แตการทจะมองเหนเหตผลทแทจรงของขออางขอน เราตองกลบไปมองวา ทจรงแลวคณเสยเวลาไปกบเรองอะไรกนแนในขณะทคณก าลงเขยน โคด หลายๆ คนจะท าการ เทสท ระบบกตอนทการพฒนาเขาสชวงทายๆ ของโปรเจคแลว กคอ phase ของการ เทสท ซงถาจะเปรยบเทยบ กจะเหมอนกบการตดหญาในสนามดวยกรรไกรตดหญา ถาคณลงมอท าตงแตเนนๆ ในขณะทสนามมเพยงตนหญาเตยๆ การตดหญากจะท าไดงาย แตถาคณปลอยไวนานเกนไป หญาในสนามกจะสงและหนาขน การตดหญากจะท าไดยากกวาเดม หรออาจจะตองเปลยนไปใชเครองมอทมประสทธภาพมากกวาเดม ราคากจะแพงขนอยางแนนอน
แทนทจะรอไปท าในชวงทาย ใหใช model แบบ “จายเทาทเราจะไป” (pay-as-you-go) เพอใหตนทนโดยรวมนอยกวาในระยะยาว โดยการเขยน เทสท แตละ เทสท ควบคไปกบการเขยน โคด ไมมการรอไปท าครงเดยวในตอนทาย คณจะ
พบวา bug โดยรวมจะลดลงไปมากถาคณคอยทดสอบ โคด ของคณอยางสม าเสมอ เวลาทเสยไปในแตละครงทเรา เทสท จะเพมขนเพยงเลกนอยเทานนเมอเทยบกบการ เทสท ในตอนทาย และมความเสยงสงกวาดวย
เราจะแสดงใหคณเหนขอดขอเสยระหวาง การ “เทสท เดยวน” (test-now) กบการ “เทสท ทหลง” (test-later)
การ “เทสท เดยวน” นน productivity ของงานจะเปนเสนตรงอยางสม าเสมอเพราะคณจะท าไปทละฟงกชนและเทสทไปทละฟงกชน เมอยนทเทสทของฟงกชนนนผานทงหมดจงจะเรมพฒนาฟงกชนตอไป การแกไขกท าไดงายเพราะโคด เพงจะ
ถกเขยนขนมา ในขณะทการ “เทสท ทหลงนน” productivity ทไดจะอยในรปของ exponential คอในชวงแรกของ
การพฒนาจะม productivity สงกวาเมอเทยบกบแบบแรก แตเมอระยะเวลาผานไป productivity จะลดลง เพราะ
นกพฒนาจะตองแบงเวลาสวนหนงออกไปเพอแก bug และมนจะมากขนเรอยๆ ตามปรมาณของ ฟงกชน ท
implement เสรจและถก เทสท ซงในกรณทแยทสด ถาทรพยากรทงหมดของทม จะตองถกทมไปเพอ debug โคด แลว
ละก นนจะเทากบ productivity ของทมตดลบ เพราะเปนการลงแรงเตมทแตไมไดผลงานใหมๆ ใดๆ เลยนอกจากการแก
bug ของ feature ทควรจะเสรจแลว ยงถา โคด นนเปน โคด ทเขยนขนมาเมอสองสปดาหหรอเมอเดอนทแลว คณยงตอง
ใชเวลาเพอรอฟนวา โคด นนมไวเพออะไร นนจะยงท าให productivity ลดลงไปอก
รปท 1.1 เปรยบเทยบระหวาง การ “เทสท ไปเขยนไป” กบการ “เทสท ครงเดยวในตอนทาย”
ขอย าวาการเทสทนนมตนทนเสมอ การเขยนไปเทสทไปกมตนทน ซงมนจะท าใหตนทนโดยรวมเพมขน (ทงเวลาทตองใช และ
เงนทตองจาย) แตเมอเทยบกบกราฟทางดานขวาซง productivity ตกลงจนตดลบแลว มนจะท าให project มปญหามากกวาและเกดตนทนทไมเกดมลคามากกวามาก
เพราะฉะนนถาคณคดวาคณไมมเวลาทจะเขยน ยนท เทสท เพอ เทสท มนตอนนละก ลองพจารณาค าถมเหลาน:
1. คณใชเวลาเทาไหรในการ debug โคด ทง โคด ในสวนทเปนของคณเอง และ โคด ทคนอนเขยนไว
2. คณใชเวลาเทาไหรในการแกไข โคด ทคณคดวามนท างานไดใน แตมนกลบท างานไมไดในตอนทาย
3. คณใชเวลาเทาไหรในการแก bug แตละตว
ส าหรบคนทท างานโดยไมไดใช ยนท เทสท นน เวลาทตองใชในการแก bug เหลานจะเพมขนอยางรวดเรว และยงคงเพมเรว
ขนเรอยๆ ตลอดชวงชวตของโปรเจคนน การเขยน ยนท เทสท ทด จะชวยลดเวลาเหลานนลง ซงเมอน าเวลาในการท างานทง 2
วธมาเปรยบเทยบกนแลว เวลาทเราใชในการแก bug ทหลงนน จะเทากนหรอมากกวาเสมอ เพราะเราตองเสยเวลาเพมขน
เพอหาวา bug เหลานนเกดทจดไหนของ โคด และไมอาจคาดเดาไดดวย เมอเอาเวลานนมาเฉลยเพอท า ยนท เทสท เราจะพบวากลบมเวลาเหลอเพอท าอยางอนดวยซ าไป
มนใชเวลานานเกนไปในการ run เทสท
มนไมควรเปนอยางนน ยนท เทสท สวนใหญใชเวลาท างานแคกระพรบตาเดยว มนควรจะ run ไดครงละเปนรอยหรอพน ยนท
เทสท ตอการ run เทสท หนงครง และควรจะจบไดในเวลาไมกวนาท
แตกเปนไปไดทมนจะใชเวลานาน ในกรณนคณควรจะแยก ยนท เทสท ทใชเวลานานออกจาก ยนท เทสท ทใชเวลาสนๆ ซง N
ยนท จะม ฟงกชน ทเขามาชวยในเรองน (ซงเราจะมาพดถงในบทตอๆ ไป) และน า ยนท เทสท ทใชเวลา run นานไป เทสท
เฉพาะในชวงทท า automation build หรออาจจะ run manual ทกเชาในขณะทคณก าลงเชค email กได และ run ยนท เทสท
สนๆ เมอมการเปลยนแปลงทส าคญๆ ในระหวางทคณ check-in โคด เขาไปยง repository กได
เปนไปไมไดทจะเอาโคดเกามา เทสท
หลายคนอาจจะแนะน าวาใหปลอย โคด ทไมสามารถน ามา เทสท ไดไวอยางนน เพราะ โคด เดมทไมไดท า ยนท เทสท มนมวมาก เปนไปไมไดเลยทจะเอา ยนท เทสท แทรกเขาไปตรงกลางแลว เทสท มน ถาจะ เทสท โคด เดม มนหมายถงคณตองลากเอา โคด ทเหลอทงระบบไปดวยแมวาคณตองการจะ เทสท เพยงสวนเลกๆ ในนนกตาม โคด เดมมนเปราะบางและเสยงเกนไป
ปญหานไมไดเปนเพราะ ยนท เทสทing แนนอน ปญหานเปนเพราะ โคด เดมทเขยนไวมนไมด คณตองคอยๆ refactor
โคด และคอยๆ ปรบ design ทละนอยเพอให โคด เดมเปนระเบยบมากขนไปเรอยๆ ขอเนนวาเราไมไดเขาไปแก โคด เดม
เพอท าใหมน run ยนท เทสท ได แตพลงทแทจรงของ ยนท เทสท กคอ design จะถกแกไขใหดขนโดยอตโนมตเมอน า ย
นท เทสท เขาไปใชตางหาก เพราะการเขยน โคด ใหสามารถ เทสท ไดนน design จะถกบงคบใหอยในรปของ object-
oriented ทดโดยอตโนมตนนเอง
การเขยน โคด แบบเขยนไปกลวไป (coding in a culture of fear) เพราะตองเขาไปแกไข โคด เกานน มนไมท าใหงานกาวหนาไปได มนไมดทงกบโปรเจค ไมดกบโปรแกรมเมอร และกบธรกจเองดวย น า ยนท เทสท เขาไปใชจงจะชวยใหงานเดนหนาตอไปได
มนไมใชหนาทผมทจะตองมา เทสท โคด ของตวเอง
นเปนขอแกตวทนาสนใจ ไหนลองบอกมาซวาจรงๆ แลวหนาทของคณทเปนโปรแกรมเมอรคออะไร สวนหนงของงานกนาจะ
เปน เขยน โคด ทมนใชงานไดจรง โคด นนควรจะ maintain ไดหรอเปลา ถาคณเอา โคด ของคณโยนใหทม เทสท โดยทไมม
อะไรมารบประกนเลยวามน work ละก คณไมไดท างานตามหนาทของคณเลย มนไมใชหนาทของคนอนทจะตองมาคอยเกบ
กวาด ในสงทคณท ารกเอาไว และในกรณทแยทสด คณ submit โคด ทเตมไปดวย bug เขาส production และนนจะท าใหคณ
เรมมปญหาใอาชพการงานของคณเอง ในอกดานหนง ถา เทสทer หรอ QA พบวามนยากมากทจะหา bug จาก โคด ของคณ
ละก ผลงานของคณกจะเปนทกลาวขวญถง และแนนอนคณไมตองหวงเลยวาคณจะตองตกงานเพราะ bug ใน โคด ของคณ
ฉนไมรจรงๆ วา โคด นนมนควรจะท างานยงไง กเลยไมรจะ เทสท ยงไง
ถาคณไมรจรงๆ วา โคด นนมนท างานยงไง หรอมไวเพออะไร กเปนไปไดวานไมใชเวลาทจะมา เทสท มน การน า
prototype มาชวยนาจะเปนขนแรกทจะชวยใหเขาใจ requirement ไดชดเจนขนเพราะถาคณไมรวา โคด นนมนท างานยงไง แลวคณจะรไดยงไงวามนท างานถกตอง
แตมน compile ผานนะ
OK... คงไมมใครเอาขออางนมาใชหรอก อยางนอยกไมพดออกมา แตมนกงายทจะถกกลอมใหคดวาการ compile ผาน
คอการประทบตราอนมตวามนท างานไดแลว การ compile นนมนเปนแคเปนการบอกวา คณเขยน โคด ไดถกตองตาม
syntax เทานน ไมไดหมายความวาคณเขยน โคด ไดถกตองตามทควรจะเปน ตวอยางเชน compiler ของ C# สามารถ
บอกไดอยางงายดายวา โคด บรรทดนผด:
static void Main() {
แคพมพผดงายๆ มนควรเปนค าวา static ไมใช statuc นแคตวอยางงายๆ แตถา โคด ของคณเปนแบบนละ...
public void Addit(Object anObject) {
List myList = new List();
myList.Add(anObject);
myList.Add(anObject);
// more code
}
มนหมายความวาคณตองการเพม object เดยวกนเขาไปใน list สองครงจรงๆ หรอคณเขยนผด? compiler บอก
ความแตกตางไมได คณเทานนทบอกไดวาตกลงคณตงใจทจะท าอะไรกนแน (การใช tool ทสามารถ generate เทสท ได
อตโนมตกมปญหาแบบเดยวกนน เพราะ tool จะสราง เทสท โดยใช โคด ของคณเทานน)
ผมถกจางมาเขยน โคด นะ ไมไดถกจางมาเขยน เทสท
ตรรกะแบบเดยวกนเลย คณไมไดถกจางมาเพอใชเวลาทงวนในการแก bug เหมอนกน คณถกจางมาเพอเขยน โคด ทใชงาน
ได และ ยนท เทสท จะเปนเครองมอทถกน ามาใช เพอใหมนเปนแบบนน กเหมอนกบ editor, IDE และ compiler นนแหละ
ฉนคงรสกผดทท าให เทสทer และ QA ตองตกงาน
ไมตองหวง เราก าลงพดถงยนทเทสท เทานน มนเปนการ เทสท ในระดบ low-level มนถกออกแบบมาเพอพวกเรา
โปรแกรมเมอร มนยงมงานอนๆ ทจะตองท าอก เชน functional testing, performance
test,environment test, verification และ validation test, formal analysis และอนๆ อกมากมาย
บรษทของฉนคงไมยอมใหฉน run ยนท เทสท บนระบบงานจรงหรอก
โวว... เราก าลงพดถง ยนท เทสท ส าหรบ developer ไมใชบน production ทท างานจรง ถงแมวาคณจะเอา เทสท
เดยวกนนไป run บนระบบทท างานจรงได มนกไมไดเรยกวา ยนท เทสท แลว จง run ยนท เทสท บนเครองของคณ ใช
database ของคณเอง หรอใช Mock Object กได (เราจะพดถงมนในบทท 6)
ถาแผนก QA หรอฝาย เทสทing ตองการ run เทสท เหลานนบน production จรงๆ ละก คณอาจจะเขาไปชวยเหลอเพอให
ขอมลทางเทคนคเพอใหเคาสามารถ เทสท ได แตในทางปฎบต มนคงไมใชการท า ยนท เทสท แนๆ
แนนอน เราท า ยนท เทสท อยแลว
ยนท เทสทing เปนหนงในหลายๆ วธ ทโดยธรรมชาตแลวโปรแกรมเมอรตองท าอยางตงใจและกระตอรอรน ถาสมาชกในทม
ไมมความกระตอรอรนละก เปนไปไดทพวกเขาอาจจะท า ยนท เทสท อยางผดๆ ลองดวาการท า ยนท เทสทing ในทมของคณนนเปนเหมอนตวอยางเหลานหรอไม
ทจรงแลว ยนท เทสท กคอ integration เทสท ทจ าเปนตองมการ setup และ เทสท โคด มากมาย ใชเวลา
run นาน และตองใช resource ตางๆ เชน database หรอ service บน network
มการเขยน ยนท เทสท นอยมาก มกถกน ามาใชเพอทดสอบใน case ปกตเทานน ไมมการ เทสท ในกรณอนๆ เชน
เมอเกด exception หรอปญหาอนๆ และไมไดบอกชดเจนวา โคด ทถก เทสท นนควรเปนยงไง
ยนท เทสท ไมไดถกปรบปรงใหทนสมย เทสท ถกละเลยหรอถกลบไปเมอมน เทสท ไมผาน หรอไมม ยนท เทสท
ใหมๆ ถกเพมเขาไปแมวาจะพบ bug ใหมๆ กตาม ถาคณพบพฤตกรรมเหลาน แสดงวาทมของคณไมไดท า ยนท เทสท อยางมประสทธภาพและเหมาะสม แนะน าใหทกคน
กลบไปอานเรอง ยนท เทสท ใหม สงไปฝกอบรม หรอใชเทคนค pair programming เพอปรบโลกทศนใหมใหถกตองอกครง
1.7 Roadmap ในบทท 2 “Your First ยนท เทสทs” จะพดถงภาพรวมของการเขยน เทสท จากนนเราจะมาดวธการใช Nยนท เพอเขยน เทสท
กนในบทท 3 แลวเราจะใชอก 2-3 บทเพอบอกสงทจ าเปนทคณตองรเกยวกบการ เทสท และจะ เทสท มนไดยงไง หลงจากนน
เราจงจะมาดคณสมบตทส าคญของการท า เทสท ทดในบทท 7 ตามดวยสงทจ าเปน ทจะท าใหการ เทสท ในโปรเจคนนเปนไป
อยางมประสทธภาพในบทท 8 ในบทนยงพดถงวธการทจะรบมอกบ โปรเจคเดมทม โคด เกาอยแลวอกดวย จากนนเราจะมาด
กนวา เทสทing นนมผลยงไงกบการ design ทดกวาเดมในบทท 9 “Design Issues” และเราจะจบดวยการ overview การ
เทสท ส าหรบ GUI ในบทท 10
ใน Appendix จะมขอมลเพมเตมทมประโยชน เชน ปญหาทมกจะเจอกนเมอใช ยนท เทสท, การ extend Nยนท, การตดตง N
ยนท เปนตน เพราะฉะนน นงใหสบาย ผอนคลาย และยนดตอนรบสโลกของการเขยน โคด ทดกวาเดม