ป้ายกำกับ: Unit Testing

Unit Testing Frameworks: การเขียน Unit Test และ Assertion ด้วย Jest / Vitest สำหรับ JavaScript/TypeScriptUnit Testing Frameworks: การเขียน Unit Test และ Assertion ด้วย Jest / Vitest สำหรับ JavaScript/TypeScript

ในโลกของการพัฒนาซอฟต์แวร์ที่ซับซ้อน การพึ่งพาการทดสอบแบบ End-to-End เพียงอย่างเดียวไม่เพียงพออีกต่อไป เมื่อโค้ดเบสมีขนาดใหญ่ขึ้น การรับประกันว่าแต่ละฟังก์ชันหรือโมดูลย่อยทำงานอย่างถูกต้องและเป็นอิสระจากส่วนอื่น ๆ จึงเป็นสิ่งจำเป็นอย่างยิ่ง นี่คือจุดที่ Unit Testing เข้ามามีบทบาทสำคัญ

บทความนี้จะเจาะลึกถึงการใช้ Unit Testing Frameworks อย่าง Jest และ Vitest ซึ่งเป็นเครื่องมือที่ทรงพลังสำหรับการเขียนชุดทดสอบใน JavaScript/TypeScript โดยเฉพาะอย่างยิ่งเมื่อเราต้องทดสอบ Logic ธุรกิจที่เกี่ยวข้องกับฐานข้อมูลอย่าง PostgreSQL

Unit Testing คืออะไร และทำไมต้องใช้ Jest/Vitest?

Unit Testing คือการทดสอบหน่วยที่เล็กที่สุดของแอปพลิเคชัน (เช่น ฟังก์ชัน, คลาส, หรือโมดูล) เพื่อยืนยันว่าหน่วยนั้นทำงานตามที่คาดหวังไว้โดยไม่ขึ้นอยู่กับสภาพแวดล้อมภายนอก (Isolation) Jest และ Vitest ได้รับความนิยมอย่างสูงเนื่องจากความเร็วในการรันเทสต์, การรองรับ TypeScript ที่ยอดเยี่ยม, และระบบ Assertion ที่ใช้งานง่าย

หัวใจของการทดสอบ: Assertion และ Mocking

หัวใจสำคัญของการทำ Unit Test คือ Assertion ซึ่งเป็นคำสั่งที่ใช้ยืนยันผลลัพธ์ที่ได้จากการรันโค้ด เช่น การยืนยันว่าค่าที่ส่งกลับมาจากการเรียกฟังก์ชัน `get_user_count()` ต้องเท่ากับจำนวนที่คาดไว้

เมื่อเราทำงานกับ PostgreSQL ข้อมูลมักจะมาจากชั้น Persistence (เช่น ORM หรือ Query Builder) การทดสอบโดยตรงกับฐานข้อมูลจริงจะทำให้เทสต์ช้าและไม่เสถียร ดังนั้น เราจึงใช้เทคนิค Mocking เพื่อจำลองการตอบกลับของฐานข้อมูล (Database Dependency) ทำให้ Unit Test ของเราสามารถรันได้อย่างรวดเร็วและเชื่อถือได้เสมอ

ตัวอย่างการทดสอบ Logic ธุรกิจที่เชื่อมต่อกับ PostgreSQL

สมมติว่าเรามีฟังก์ชันใน JavaScript/TypeScript ที่มีหน้าที่นับจำนวนผู้ใช้ที่ Active จากฐานข้อมูล PostgreSQL โดยเราจะใช้ Jest ในการเขียนเทสต์:

JavaScript

// user-service.test.js

describe('User Service Logic', () => {
  // Mocking the database layer interaction
  const mockDbQuery = jest.fn();

  it('should correctly count active users from PostgreSQL', async () => {
    // 1. Setup: กำหนดให้ mock function ส่งค่าที่คาดหวัง
    mockDbQuery.mockResolvedValue({
      rows: [{ count: 15 }] // จำลองผลลัพธ์จาก SELECT COUNT(*) FROM users WHERE status = 'active'
    });

    // 2. Execution: เรียกฟังก์ชันที่กำลังทดสอบ
    const count = await userService.getActiveUserCount(mockDbQuery);

    // 3. Assertion: ยืนยันว่าผลลัพธ์ที่ได้ถูกต้อง
    expect(count).toBe(15);
    
    // 4. Assertion: ตรวจสอบว่ามีการเรียกใช้ query ด้วยเงื่อนไขที่ถูกต้อง
    expect(mockDbQuery).toHaveBeenCalledWith(
      "SELECT COUNT(*) FROM users WHERE status = 'active';"
    );
  });
});

จากตัวอย่างนี้ เราไม่ได้เชื่อมต่อกับ PostgreSQL จริง แต่เรากำลังทดสอบว่า Logic ของเราเรียกใช้ Query ที่ถูกต้อง และจัดการกับผลลัพธ์ที่ได้จาก PostgreSQL ได้อย่างถูกต้องตามที่เรากำหนด Mock ไว้

บทสรุป

การใช้ Unit Testing Frameworks อย่าง Jest หรือ Vitest ไม่ได้เป็นเพียงทางเลือก แต่เป็นรากฐานสำคัญของการพัฒนาซอฟต์แวร์ระดับมืออาชีพ การเรียนรู้ที่จะแยก Logic ธุรกิจออกจาก Dependency ภายนอก (เช่น PostgreSQL) และใช้เทคนิค Mocking อย่างเชี่ยวชาญ จะช่วยให้โค้ดของเรามีความเสถียร, บำรุงรักษาได้ง่าย, และลดความเสี่ยงในการเกิดบั๊กได้อย่างมีนัยสำคัญ ทำให้ทีมพัฒนาสามารถส่งมอบผลิตภัณฑ์ที่มีคุณภาพสูงได้อย่างมั่นใจ