ป้ายกำกับ: Regression

Unit Test คืออะไร ? ทำไมโปรแกรมเมอร์มือโปรถึงขาดไม่ได้Unit Test คืออะไร ? ทำไมโปรแกรมเมอร์มือโปรถึงขาดไม่ได้

ในการเขียนโปรแกรม หลายคนอาจเคยเจอเหตุการณ์ “แก้จุดหนึ่ง พังอีกจุดหนึ่ง” หรือที่เรียกว่า Regression การเขียน Unit Test จึงเปรียบเสมือนการสร้าง “เกราะป้องกัน” ให้กับ Code ของเรา เพื่อให้มั่นใจว่าฟังก์ชันเล็ก ๆ แต่ละส่วนทำงานได้ถูกต้องตามที่ตั้งใจไว้


Unit Test คืออะไร ?

Unit Test คือการทดสอบซอฟต์แวร์ในระดับที่เล็กที่สุด ( Smallest unit ) ซึ่งโดยปกติหมายถึงการทดสอบ “ฟังก์ชัน” ( Function ) หรือ “เมธอด” ( Method ) เพียงอย่างเดียว โดยไม่สนใจส่วนประกอบภายนอก เช่น Database หรือ API อื่น ๆ


หลักการสำคัญของ Unit Test ( FIRST Rule )

  • Fast: ต้องรันได้เร็วมาก ( หลักมิลลิวินาที ) เพื่อให้รันได้บ่อย ๆ
  • Independent: เทสแต่ละตัวต้องไม่ขึ้นต่อกัน ลำดับการรันต้องไม่มีผล
  • Repeatable: รันกี่ครั้ง ผลลัพธ์ต้องเหมือนเดิมเสมอ
  • Self-Validating: ต้องบอกผลลัพธ์ได้ชัดเจนว่า “ผ่าน ( Pass )” หรือ “ไม่ผ่าน ( Fail )” โดยไม่ต้องให้คนมาตีความ
  • Thorough/Timely: ครอบคลุมกรณีต่างๆ และควรเขียนพร้อม ๆ กับการเขียน Code

โครงสร้างของ Unit Test ( AAA Pattern )

เพื่อให้ Unit Test อ่านง่ายและเป็นระเบียบ เรานิยมใช้โครงสร้าง AAA

  • Arrange: การเตรียมข้อมูลและสภาพแวดล้อมที่จำเป็นสำหรับบททดสอบ
  • Act: การเรียกใช้งานฟังก์ชันหรือเมธอดที่ต้องการทดสอบจริง
  • Assert: การตรวจสอบว่าผลลัพธ์ที่ได้ ( Actual ) ตรงกับที่คาดหวังไว้ ( Expected ) หรือไม่

ทำไมเราต้องเขียน Unit Test ?

  • ลด Bug ในระยะยาว: การเจอข้อผิดพลาดตั้งแต่ตอนเขียน Code แก้ไขได้ง่ายและราคาถูกกว่าการไปเจอตอน Deploy แล้ว
  • กล้าที่จะ Refactor: เมื่อเรามี Unit Test ครอบคลุม เราจะกล้าปรับปรุง Code ให้สะอาดขึ้น เพราะถ้าระบบพัง เทสจะแจ้งเตือนเราทันที
  • เป็น Documentation ไปในตัว: Code ของ Unit Test จะบอกเราว่าฟังก์ชันนี้ควรรับค่าอะไร และได้ผลลัพธ์แบบไหน
  • ประหยัดเวลา Manual Test: ไม่ต้องคอยกดรันโปรแกรมหน้าจอเดิม ๆ ซ้ำ ๆ เพื่อเช็คว่าพังไหม

ตัวอย่างการเขียน Unit Test ( Pseudo Code )

สมมติเรามีฟังก์ชันบวกเลขง่าย ๆ

// ฟังก์ชันที่ต้องการทดสอบ
function add(a, b) {
    return a + b;
}

// Unit Test
test('ควรคืนค่าเป็น 5 เมื่อบวก 2 กับ 3', () => {
    // 1. Arrange
    const num1 = 2;
    const num2 = 3;
    const expected = 5;

    // 2. Act
    const result = add(num1, num2);

    // 3. Assert
    expect(result).toBe(expected);
});

ข้อแนะนำสำหรับมือใหม่

  • อย่าทดสอบ Logic ที่ซับซ้อนเกินไปในหนึ่งเทส: หนึ่งเทสควรตรวจสอบเพียง “เรื่องเดียว”
  • ใช้ Mocking: หากฟังก์ชันของคุณต้องไปดึงข้อมูลจาก Database ให้ใช้เครื่องมือจำลอง ( Mock ) ข้อมูลขึ้นมาแทน เพื่อรักษาความเร็วและความเป็นอิสระของ Unit Test
  • เริ่มจากเส้นทางที่ถูกต้อง ( Happy Path ): เขียนเทสให้เคสที่ทำงานปกติผ่านก่อน แล้วค่อยเขียนดักเคสที่น่าจะพัง ( Edge Cases )

สรุป

การเขียน Unit Test อาจดูเหมือนเสียเวลาในช่วงแรก แต่ในโปรเจกต์ที่มีความซับซ้อนหรือต้องดูแลรักษาในระยะยาว มันคือการลงทุนที่คุ้มค่าที่สุดอย่างหนึ่งของเหล่านักพัฒนาครับ


อ่านเพิ่มเติม