[PHP] ฝึกเขียน Test EP 2 Fizzbuzz

บทความนี้จะเป็นการฝึกเขียน Test FizzBuzz เกมง่ายๆ โดยหลายๆคนคงจะได้ผ่านบททดสอบนี้ คล้ายๆกับการเริ่มเขียนโปรแกรมต้องเขียน Hello world นั่นแหละยังไง ยังงั้นเลย โดยผมอาจจะไม่ได้อัพขึ้น git hub ทีละขั้นนะครับอาจจะเป็นแบบไฟล์สำเร็จเลยแล้วอ่านเอาจากบทความนี้นะครับ ถ้าใครมีคำถามหรือข้อเสนอก็รบกวนเขียนฝากไว้ด้านล่างนะครับ

เริ่มดูโจทย์แล้วคิด

หลายๆคนก็น่าจะเป็นเหมือนผมได้โจทย์มาอ่านเสร็จเริ่มเขียนเลย อย่างแรกเราไปดูโจทย์หรือ Requirement กันก่อนแหละเพื่อให้เราเข้าใจว่าโจทย์ต้องการอะไร แล้วเราจะเริ่มเขียน Test อะไรก่อน ขอออกตัวก่อนนะครับว่าผมไม่ได้เชี่ยวชาญนะครับ เพราะฉะนั้นอาจจะเริ่มคิดไม่เหมือนคนอื่น อย่างที่บอกไปในตอนแรกถ้าคิดต่างขอแชร์กันได้นะครับ ผมจะได้เปิดโลกมากขึ้น เอาต่อ โจทย์เป็นดังนี้

โจทย์

เกม Fizzbuzz จะให้เขียน function หรือ class ก็ได้ โดยเมื่อรันแล้วจะทำการ echo/print ตัวเลข โดยตัวเลขตำ่สุดคือ 1 จนถึงจำนวนที่ใส่โดยถ้าไม่ส่งค่าให้ตัวเลขสุดท้ายอยู่ที่ 15 และหากตัวเลขใดหารด้วย 3 ลงตัวให้ echo/print คำว่า ‘fizz’ และหากตัวเลขใดหารด้วย 5 ลงตัวให้ echo/print คำว่า ‘buzz’ แทนตัวเลขนั้นๆ หากลงตัวทั้งคู่ให้ echo/print คำว่า ‘fizzbuzz’ อย่างนี้ตัวอย่างหากเราเรียกแล้วผลลัพธ์จะทำนองนี้

1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz’

จากโจทย์แค่นี้เราจะเขียน test ได้เป็นหมื่นเคสเลย ( เวอร์ไป ) เอาจริงๆก็คือเยอะอยู่นะ ถ้าเราละเอียด แต่อย่างที่เคยบอกไปในบทความฝึกเขียนครั้งแรกว่า จะเขียนจำนวนเคสเยอะหรือน้อยขึ้นอยู่กับเวลาและความรุนแรงของ function นั้นๆ หากมันเป็นเกี่ยวข้องกับหลายส่วนหรือสำคัญก็ควรจะคิดให้เยอะๆหลายๆด้านหน่อยครับโอเคเรามาคิดเรื่องเคสที่เกิดขึ้นได้ก่อนจากโจทย์มีดังนี้

  • ค่าเริ่มแรกเป็น 1
  • ค่าสุดท้ายเท่าไรก็ได้แต่ถ้าไม่ส่งก็ 15
  • หาร 3 ลงตัว echo fizz
  • หาร 5 ลงตัว echo buzz
  • หากลงตัวทั้ง 3 และ 5 echo fizzbuzz

ก่อนจะเริ่มเขียน Test แรกแนะนำให้ไป set up Test ก่อนนะครับใครยังทำไม่เป็นก็ไปดูที่นี่ครับ  [PHP] ฝึกเขียน Test กันเถอะ LV Beginner

Test แรก fizzbuzz

เริ่มต้นก็อยู่ที่เราครับว่าจะเทสอะไร คาดหวังอะไรตรงไหน ค่อยๆคิดครับไม่ต้องรีบ อย่างผมตอนแรกอยากจะลองเริ่มเทสว่าเรามี function execute ( แล้วแต่จะตั้งชื่อนะครับ ) แบบเรียกใช้โดยลองส่ง 3 เข้าไปแล้วจะได้คำว่า fizz กลับมาเราจะเขียน เทส ประมาณนี้ครับ

เมื่อลองรัน Test ดูจะพบว่าเรายังไม่ได้สร้าง class Fizzbuzz ด้วยซ้ำนะครับ เพราะฉะนั้นตัว Test นี้จะช่วยให้เราทำตามขั้นตอนได้อย่างดีครับ โดยเราจะเริ่มสร้าง class Fizzbuzz มาครับ แล้วก็สร้าง function execute ต่อเลย เสร็จเราอยากให้เทสผ่านก็ทำการ return ‘fizz’ ได้เลยครับเทสแรกเราก็จะผ่านแหละ

ต่อมาเราจะเทสว่าถ้าได้รับเลข 5 จะคืนค่าเป็น ‘buzz’ กลับมาโดยเราจะเพิ่ม Test ต่ออีกหนึ่ง function ครับเป็นดังนี้

ซึ่ง ณ ตอนนี้ Test จะช่วยเหลือเราแล้วว่าจะใส่ 3 ใส่ 5 ต่อแล้วผลออกมาอย่างที่เราต้องการไหม ? เมื่อเทสก็จะไม่ผ่านติดตัวแดง ผมอาจจะไม่ได้ทำภาพให้ดูนะครับไปดูบทแรกที่สอนนะครับ บทนี้จะมาทำให้ดูว่าคิดยังไง ทำยังไงครับ ต่อมาเราต้องไปแก้ตัวไฟล์ Fizzbuzz.php ให้เทสผ่านนะครับโดยจะเป็นอย่างนี้ครับ

ก็จะเทสผ่านนะครับ แต่สังเกตุไหมครับว่าถ้าส่งตัวเลขอื่นเข้าไปจะเป็นยังไง นั่นแหละครับต่อไปเราก็ลองส่งตัวเลขที่ไม่ใช่ 3 หรือ 5 ดูครับ ว่าจะเป็นอย่างไร กลับไปแก้ไข FizzbuzzTest.php ครับ คราวนี้เราจะทดสอบเรื่องที่ว่าส่งค่าเป็น 1 ก็ต้องกลับมาเป็น 1 หรือ 2 ก็ต้องส่งกลับเป็น 2 ครับลองทีละอันครับ

เราก็จะไปแก้ไขง่ายด้วยว่าเพิ่ม return $number; จะได้แล้วครับดังนี้

ถ้าแก้ไขครั้งนี้เราจะรองรับ 1 , 2  , 4 ได้หมดแต่ … คำถามคือเรามั่นใจได้อย่างไร ? แน่นอนครับเราทำ Test อยู่ก็ทำ Test ในสิ่งที่เราไม่มั่นใจไงครับ งั้นเราก็ลองดูว่าส่ง 2 , 4 เข้าไปได้กลับมาเป็นอย่างที่เราทำไหม

ลองดูว่าผ่านไหมนะครับ เสร็จอย่างที่เราดูว่าโค้ดที่เราเขียนนั้นยังไม่รองรับเลข 6 ซึ่งหาร 3 ลงตัวมันควรจะเป็นคำว่า ‘fizz’ ออกมา ถ้าเราไม่มั่นใจก็ลองครับอย่างที่บอก

สังเกตุนะครับชื่อ test เราควรจะเขียนให้เข้าใจด้วยเวลามันขึ้นตัวแดงเราจะได้อ่านแล้วรู้ว่ามันผิดตรงไหนอย่างไร เมื่อรันเทสเราจะไม่ผ่าน เพราะโค้ดที่เราเขียนในตอนแรกนั้นมันเช็คว่าต้องเท่ากับ 3 นะครับไม่ใช่หาร 3 ลงตัวเราก็ต้องไปแก้ไข function ดูครับเป็น

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

ตอนนี้เราสำเร็จไปหลายเคสแหละเราลองมาทบทวนดูครับว่าตอนนี้เราเทสอะไรผ่านไปแล้วแล้วเหลืออะไรบ้าง

  • ค่าเริ่มแรกเป็น 1 ( ยังไม่ได้ทำ )
  • ค่าสุดท้ายเท่าไรก็ได้แต่ถ้าไม่ส่งก็ 15 ( ยังไม่ได้ทำ )
  • หาร 3 ลงตัว echo fizz ( ทำแล้ว )
  • หาร 5 ลงตัว echo buzz ( ทำแล้ว )
  • หากลงตัวทั้ง 3 และ 5 echo fizzbuzz ( ยังไม่ได้ทำ )

โอเคงั้นต่อไปเราเทสเรื่องถ้าหากเป็นตัวเลข 15 คือหารลงด้วย 3 และ 5 จะคือค่ากลับมาเป็น fizzbuzz ดูครับดังนี้

เสร็จแล้วเราก็กลับไปแก้ไขไฟล์ Fizzbuzz.php เป็น

โอเคเสร็จแล้วคราวนี้เกมมันนี้เราต้องมีอีก 1 function สำหรับการทำการวนเลขให้นั่นแหละ เพราะฉะนั้นเราจะทดสอบการวนเลขก่อนครับโดยเทสหน้าตาจะเป็นแบบนี้ครับ

โดยเมื่อรัน test ระบบจะแจ้งว่าเรายังไม่มี function play ก็แน่นอนแหละ ก็ไปสร้าง function play ครับแล้วก็ return ง่ายๆมาเลยแบบที่เทสมันต้องการดังนี้

แต่ๆ เกมนี้มันไม่ได้จำนวนกัดว่าจะใส่ให้มันวนเลขเท่าไร เช่น ถ้าเราใส่ play(20) มันก็ควรจะวน 1 – 20 ถูกต้องไหมครับ เพราะฉะนั้นเราก็ต้องลองครับเขียนเคสเลย

คราวนี้เราต้องแก้ไขให้ function เราวนเลขแหละโดยถ้าไม่ใส่มาเราจะกำหนดให้เป็น 15 เหมือนที่โจทย์ตั้งไว้ครับเป็นดังนี้

คราวนี้เราจะทำการทดสอบ 2 เคสนั้นได้แล้วคือ ค่าเริ่มต้นถ้าไม่ส่งมาให้เป็น 1 และค่าสุดท้ายเป็น 15 แต่ถ้าส่งมาก็จะนับเลขตามที่เราใส่ ลองรันเทสดูครับ สุดท้ายเราจะสามารถ refactor test ก็ได้นะครับเมื่อตอนแรกเราให้ค่าเป็น 1 – 15 แต่คราวนี้เราต้องการให้ทำการวนเลขและทำการเช็คค่าด้วยว่าเป็น fizz หรือ buzz เราสามารถแก้ไข Test เป็นดังนี้

และสุดท้ายเราก็รันเทสแล้วแก้ไขไฟล์ที่เราเทส ดังนี้ครับ

ก็จะเสร็จแล้วครับสำหรับบทนี้ ใครอยากดูไปดูที่ github ได้ครับ https://github.com/oxygenyoyo/fizzbuzz_php

อ้าวจบแล้ว ?

เอาจริงๆผมเชื่อว่าหลายๆคนก็จะมีไอเดียแล้วว่าจะเทสอะไรต่อเช่น ทำไมไม่เขียนเทสสำหรับการส่งค่าเป็นค่าลบ หรือเป็น String สำหรับค่าตัวเลขสุดท้ายเช่น play(-1) หรือ play(‘test’) แล้วให้คืนค่าแบบที่ exception มาก็ได้ หรือให้แสดงข้อความแจ้งเตือนก็ได้ ซึ่งถ้าหากคุณอ่านถึงตรงนี้แล้วคิดว่ามีหลายเคสที่ผมไม่ได้ทำ แปลว่า คุณเริ่มเข้าใจแล้วว่าการเขียน เทสมันช่วยอะไรบ้าง

  • ทำให้เรานึกถึงความเป็นไปได้ของโค้ดของเรา
  • ทำให้เรารอบคอบ
  • ทำให้เราไม่ต้องใส่ค่าเทสที่เคยทำไปแล้ว ทำซ้ำๆให้เรา

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

ถ้าหากมีอะไรที่ผมเขียนพลาดหรือมีอะไรที่ไม่เข้าใจลองมาแชร์กันนะครับ

 

คุณอาจจะชอบบทความเหล่านี้

Code เป็นแล้ว Code ดีไหม ?... หลายๆคนที่เป็นนักพัฒนาโปรแกรม ( Programmer ) นั้นคงมีหลายครั้งในชีวิตที่เจอปัญหาว่า Code ตัวเองอ่านไม่ออกภายหลังจากที่เคยทำไปเมื่อ 3 เดือนที่แล้ว ...
The Art of Testing ReactJS and The Emerging Reason... สรุปจากงาน The Art of Testing ReactJS and The Emerging Reasonreact นะครับโดยตัวงานจะเป็นการพูดถึง React จะ test ยังไง การ test มีกี่แบบและแตกต่างกันยั...
TDD ไม่รู้จักหรอกเอาแค่เริ่มรู้จัก Test ก่อน... บทความนี่อยากแนะนำเกี่ยวกับอีกสกิลหนึ่งที่คนเป็นนักพัฒนาต้องพยายามเข้าใจมัน ทั้งๆที่มันค่อนข้าง abstract และงงๆสำหรับคนบางคนที่เขียนโปรแกรมมาซักพัก หล...

ชอบเนื้อหาแบบนี้ไหมครับ ?

ถ้าชอบอย่าลืมติดตามง่ายๆด้วยการกรอกอีเมลของคุณในช่องด้านล่าง ผมจะส่งบทความดีๆเกี่ยวกับ programming, event, lifestyle ต่างๆมาสรุปให้แก่คุณก่อนใคร และยังมีกิจกรรมดีๆ ซึ่งคุณจะไม่พลาดทุกการเคลื่อนไหวอย่างแน่นอน

เป็นโปรแกรมเมอร์ที่ตามหาคุณค่าของชีวิตและความฝันในวัยเด็ก ชอบเล่นเกม เรียนรู้ทุกอย่าง ชอบเจอคนใหม่ๆ งานสังคมทุกชนิด ออกกำลังกายในวันว่าง อ่านหนังสือ มีเว็บรีวิวหนังสือด้วย www.readraide.in.th