TDD != Unit Testing

ความจริงกะว่าวันนี้จะมาตอบคำถามที่ตัวเองถามไว้ แต่คอยให้คุณ @kluak110 มาแสดงความคิดเห็นก่อน เพราะเป็นเจ้าของสถานการณ์ตัวจริง

หลังจากสองสามวันที่ผ่านมาผมก่อการไปพักใหญ่ ทำให้เกิดการกระเพื่อมได้พอสมควร โพสของผมคึกคักที่สุดตั้งแต่เริ่มเขียนให้ agile66 มา ผมรู้สึกดีใจที่เรามี agile evangelists ที่มีความรู้ความเข้าใจในหลักการ ของ agile ได้ในระัดับสูง ทั้งคุณ Nattanicha, @sinapam, Up1 และ คุณ @juacompe (ตกใครไปขออภัย) กว่าจะมาถึงวันนี้ได้ ไม่ใช่ว่าทำๆ งานไปแล้วจะได้มา ต้องทำต้องรู้ต้องคิดต้องอ่านต้องลองผิดลองถูก มามากมาย

ผมพบว่าการแปลความของคำว่า unit testing ของทุกคน เหมือนหรือคล้ายกัน คือ

1. unit testing (ต้อง)ทำโดย developer
2. unit testing เป็น automate และทำโดยใช้ xUnit library tool
3. unit testing จำเป็นต้องเป็นต้องใช้เทคนิค white box test

มาคิดก็ถึงบางอ้อ นี่หรือคือ generation gap พอเราเกิดคนละยุคมุมมองต่างๆ ก็เปลี่ยนไปไม่ตรงกัน ส่วนตัว ผมนั้นเกิดในยุคดั้งเดิม ภาษาที่เรียกได้ว่าฮิตและสอนกันในมหาลัยคือ COBOL(COmmon Business-Oriented Language), FORTRAN (FORmula TRANslation) – [ถ้าเป็นสมัยนี้จะสะกดว่า Fortran จะสะกดตัวใหญ๋หมดได้ต้องเก่าจริง], และ PL/I (Programming Language One) – [อ่านว่า พี่แอลวัน] ที่พยายามบอกคือ ภาษาพวกนี้เป็น 3rd Generation Programming Language (3rd GL) ครับ สมัยนั้นฝันกันว่าวันหนึ่งเราจะสั่งคอมพิวเตอร์ ด้วยภาษาใกล้เคียงมนุษย์ เรียกว่า 4th GL แต่ก็ไม่เคยทำจริงได้สักที OOP ในเวลาต่อมา คือการแก้ไข 3rd GL ในอดีต และ scripting language (Ruby, Groovy, Python) ที่กำลังฮิตตอนนี้ก็คือภาคแก้ไขของ OOP อีกทีหนึ่ง แต่ก็ยังหนีจากยุคสามไปไม่พ้น อาจจะอยู่ราวๆ 3.5 – 3.6

แล้วผมพร่ำรำพันถึงวันเก่าๆ ไปทำไม นั่นเป็นเพราะ คำว่า unit testing นั้น เกิดขึ้นในขณะที่ภาษายุคสาม ที่ เรียกต่อมาภายหลังว่า structural / procedural language ครองโลกอยู่น่ะสิ เพราะ ฉะนั้นการจะเข้าใจที่มาที่ไปของ unit testing ได้ต้องเข้าใจก่อนว่า โลกยุคนั้น พัฒนาซอฟแวร์กันอย่างไร โลกยุคนั้นใช้ วิธีการ (methodology) ที่ชื่อว่า V-Model ครับ

V-Model

V-Model นั้นมีรากฐานมาจาก waterfall ในแต่ละเฟสของ waterfall นั้นเราจะต้องทำการ สร้างกระบวนการทดสอบ ให้เหมาะสม (match) กัน ตามรูปนะครับ

จากรูปจะเห็นว่า กระบวนการ Requirement Gathering and Design จะเกิดแบบนี้

1. ใน Requirement Phase ขณะที่ Business Analyst เขียน Business Requirement Doc นั้น QA จะเขียน Acceptance Test Plan ควบคู่กันไป
2. ใน High Level Design Phase ขณะที่ System Analyst เขียน System Design และ Architecture Design นั้น QA ก็จะเขียน System Test Plan
3. ใน Detail Design Phase ก็เช่นเดียวกัน Designer จะเขียน Module Design และ QA เขียน Integration Test Plan และ Unit Test Plan สำหรับใช้ทดสอบ

พอจบปุ๊บทุกอย่างก็พร้อมสำหรับ การเริ่ม coding ก็เกณฑ์ coder มาทำการโค้ดตามแบบ ที่ออกแบบไว้ใน Detail Design โค้ดเดอร์ไม่จำเป็นต้องรู้หรือเข้าใจระบบ แค่อ่าน เอกสารได้ก็ทำออกมาเป็นซอฟแวร์ได้ถูกต้อง เหมือนคนงานสร้างตึก หรือสร้างสะพาน ผมจะไม่คุยว่าเป็นแนวทางที่ถูกหรือผิด เพราะกำลังเล่าประวัติศาสตร์ให้ฟัง เมื่อโค้ดเสร็จก็จะเข้าสู่ Testing Phase ซึ่ง

ใน Testing Phase นั้นเหล่า QA ก็จะงัดเอา Test Plan ที่ทำไว้มา execute ตามลำดับ คือ

1. Unit Test Plan ใช้ test ระดับ Module เรียกว่า Unit Testing
2. Integration Test Plan ใช้ test ระดับ Modules (คือตั้งแต่สอง modules ขึ้นไปทำงานร่วมกัน) เรียกว่า Integration Testing
3. System Test Plan ใช้ test ระดับ System เรียกว่า System Testing พูดอย่งนี้ก็กำปั้นทุบดินเกินไป คือจะเข้าใจระดับนี้ได้ต้องเข้าใจก่อนว่า Mainframe มี architecture ไม่เหมือน Unix based คือ Mainframe นั้นจะขยายเครื่องให้ใหญ่แค่ไหนก็ได้ เช่นรุ่น 80 cores มี RAM ได้ถึง 3 TB แต่ไม่มีใครใช้เครื่องใหญ่ยักษ์อย่างนั้นทำงาน เค้าจะแบ่งย่อยๆ ออกเป็น LPAR ย่อมาจาก Logical Partition เหมือนๆ กับ เราเอาเครื่องเรา มาลง VMWare หลายๆ ตัวอย่างนั้น เสร็จแล้วการสร้างซอฟแวร์ในสมัยนั้น เค้าจะทำให้มันซับซ้อนมากไม่ได้เพราะมันยาก ตัวอย่างเช่น Banking เค้าจะไม่สามารถทำให้ซอฟแวร์ทั้งตัวควบคุมทุกสาขาได้ เค้าจะสร้างซอฟแวร์ให้ทำงานได้สำหรับหนึ่งสาขา เรียกว่า System A ก็แล้วกัน แล้วถ้าจะตั้งสาขาที่สองล่ะ เค้าก็แค่ ก็อปปี้ โปรแกรม ของสาขาแรก ตั้งชื่อใหม่เป็น System B ทั้งสอง System นี่จะรันจาก โปรแกรมเดียวกัน แต่คนละก็อปปี้กัน แล้วถ้าต้องการรายงานรวมของทุกสาขา เค้าก็จะต้องสร้าง โปรแกรม เรียกว่า Head Office / Back Office ไล่อ่านข้อมูลจากแต่ละสาขามาประมวลผล ในอีก System หนึ่ง ซึ่งจะกินเวลาและแรงงานมาก ถ้าจำกันได้สมัยโบราณเวลาเราจะปิดบัญชีเงินฝาก เราจะต้องไปสาขาที่เราเปิด นั่นเพราะเหตุผลนี้แหละ)
4. Acceptance Test Plan ใช้ test ในขั้นตอนสุดท้ายเพื่อดูว่า ผลลัพธ์ของ software ที่ทำงานได้ถูกต้องนั้นตอบสนองต่อ Requirement ดั้งเดิมหรือไม่

ประเด็นที่ผมอยากนำเสนอคือ Unit Testing ถ้าจะแปลกันตรงๆ แล้ว ก็คือ การทดสอบระดับหน่วย คำถามต่อมาก็คือ หน่วยในที่นี้คืออะไร คำตอบมีอยู่ข้างบนแล้วคือ 1 หน่วยก็คือ 1 module ถ้าเป็นโปรแกรมเมอร์รุ่นเก่าอย่างผมจะเข้าใจทันที ว่า โมดูล คืออะไร แต่สำหรับคนรุ่นใหม่จะมองไม่ออก เพราะไม่เคยเห็น

Module คือ โปรแกรม 1 โปรแกรม หรือพูดง่ายๆ ก็คือ 1 ไฟล์ ซึ่งจะเป็นอะไรก็ได้ Logic, Screen, Constant, etc. แต่เวลาที่เรา test เรามักจะ test ที่ module ที่เ็ป็น logic เพราะจะเห็น Screen และ constant อยู่แล้วในนั้น

เพื่อให้เห็นภาพผมจะยกตัวอย่าง สมมติ โปรแกรมเรามี 3 Module คือ

1. หน้า กรอกข้อมูลลูกค้า
2. หน้า สร้างบัญชีใหม่
3. หน้า ฝากเงิน

ในการทำ unit test เราจะต้องทำ unit test แยกแต่ละหน้า แล้ว ทำ integration test รวมกัน เรียกว่า “การเปิดบัญชี” ใหม่ แล้ว ไปทดสอบ ในระดับ system เช่น เปิดแล้ว ฝากถอนถูกต้องหรือไ่ม่ แล้วจึงกลับไปดูว่า ถูกต้องตาม Requirement ตั้งต้นหรือไ่ม่ เช่น ข้อมูลลูกค้ามีข้อมูลครบ หรือไม่ เป็นต้น

ในปัจจุบันนั้น คำว่า Unit ออกจะลางเลือนไปทุกวัน เพราะหาขอบเขตไม่เจอ จะบอกว่า package ก็กว้างเกินไป จะบอกว่า Class ก็ถูก reuse เต็มไปหมด ถ้าจะบอกว่า method พอเจอ SOA เข้าไปเราก็ไม่รู้แล้วว่า method นี้มันอยู่ใน system เ้ราหรือ system คนอื่น สรุปง่ายๆ ก็คือ คำว่า Unit ก็คงคล้ายคำว่า ‘ถ่าน’ ที่ถ้าถามเด็กทุกวันนี้อาจจะไม่รู้ หรือไม่เคยเห็นว่าหน้าตาเป็นอย่างไร อาจจะคิดถึง ถ่านไฟฉาย ก็ได้

ยังไมไ่ด้เล่าไปถึง TDD เลย เอาไว้พรุ่งนี้มาต่อตอนสอง ก็แล้วกัน

Links
http://eclecticcolors.blogspot.com/2010/01/sdlc-models.html
http://en.wikipedia.org/wiki/LPAR

Advertisements

One thought on “TDD != Unit Testing

  1. Pingback: TDD != Unit Testing (3) « Korn4D Agile Blog

ใส่ความเห็น

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s