ในโลกของการพัฒนาซอฟต์แวร์ที่ซับซ้อน การพึ่งพาการทดสอบแบบ 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 อย่างเชี่ยวชาญ จะช่วยให้โค้ดของเรามีความเสถียร, บำรุงรักษาได้ง่าย, และลดความเสี่ยงในการเกิดบั๊กได้อย่างมีนัยสำคัญ ทำให้ทีมพัฒนาสามารถส่งมอบผลิตภัณฑ์ที่มีคุณภาพสูงได้อย่างมั่นใจ