Describe, Test, and It
บทนี้อธิบาย 3 ตัวพื้นฐานที่เจอบ่อยที่สุดใน Vitest คือ `describe()`, `test()`, และ `it()` ว่าแต่ละตัวมีหน้าที่อะไร ต่างกันตรงไหน และควรตั้งชื่อ suite กับ test case อย่างไรให้อ่านง่ายขึ้นตั้งแต่เริ่มต้น
Step 1
Step 1: มองโครงสร้าง test file แบบง่ายที่สุดก่อน
เวลาเปิดไฟล์ test ของ Vitest คุณมักจะเห็น 3 อย่างนี้อยู่ด้วยกันบ่อยมาก: `describe()` ใช้จัดกลุ่ม, `test()` หรือ `it()` ใช้ประกาศ test case รายข้อ, และ `expect()` ใช้ตรวจว่าผลลัพธ์ตรงกับสิ่งที่คาดไว้หรือไม่
ตัวอย่างนี้แสดงโครงสร้างพื้นฐานของไฟล์ test หนึ่งไฟล์ที่มี suite หนึ่งชุดและ test case หนึ่งข้อ
Step 2
Step 2: `describe()` คือกล่องสำหรับจัดกลุ่ม test ที่เกี่ยวข้องกัน
`describe()` ไม่ได้เป็นตัว assert ผลลัพธ์เอง แต่มันช่วยรวม test ที่พูดถึงเรื่องเดียวกันไว้ด้วยกัน เช่น function เดียวกัน, component เดียวกัน, หรือ use case เดียวกัน ทำให้ทั้งคนอ่านและ output ของ Vitest เข้าใจโครงสร้างได้ง่ายขึ้น
suite ชื่อ `loginUser` บอกทันทีว่ากลุ่ม test นี้กำลังทดสอบ behavior ของอะไร
Step 3
Step 3: `test()` คือหนึ่งกรณีทดสอบที่มี expected behavior ชัดเจน
`test()` ใช้บอกว่าเรากำลังตรวจพฤติกรรมอะไรหนึ่งข้อ เช่น คืนค่าอะไรเมื่อ input แบบหนึ่ง หรือควรโยน error เมื่อเจอสถานการณ์หนึ่ง ชื่อของ test ควรอ่านแล้วรู้ทันทีว่าเราคาดหวังอะไรจากระบบ
แต่ละ `test()` ควรมีเป้าหมายเดียว เพื่อให้อ่านง่ายและรู้ทันทีว่า fail เพราะอะไร
Step 4
Step 4: `it()` ทำงานเหมือน `test()` แต่ช่วยให้ประโยคอ่านต่อกันลื่นกว่า
`it()` ไม่มีความสามารถพิเศษเพิ่มจาก `test()` ในเชิง behavior มันเป็น alias ที่ทำงานเหมือนกัน จุดต่างหลักคือสไตล์การอ่าน เช่น เมื่ออยู่ใน `describe("sum")` แล้วตามด้วย `it("returns 5 when adding 2 and 3")` จะอ่านเป็นประโยคได้ลื่นว่า sum it returns 5 when adding 2 and 3
ตัวอย่างนี้ใช้ `it()` แทน `test()` แต่ผลการรันและความหมายในระบบยังเหมือนเดิม
Step 5
Step 5: เลือกใช้ `test()` หรือ `it()` เป็น style หลักแบบใดแบบหนึ่งในไฟล์เดียว
เพราะ `test()` และ `it()` ทำงานเหมือนกัน การสลับใช้ไปมาภายในไฟล์เดียวมักไม่ได้เพิ่มประโยชน์มากนัก แต่ทำให้ style ดูปนกันได้ง่าย ถ้าไม่ได้มีเหตุผลชัดเจน ควรเลือกหนึ่งแบบแล้วใช้ให้สม่ำเสมอทั้งไฟล์หรือทั้งโปรเจกต์
ตัวอย่างนี้แสดง style ที่สม่ำเสมอทั้งไฟล์ด้วย `it()` แต่ถ้าทีมใช้ `test()` เป็นหลักก็ให้คงแบบนั้นทั้งไฟล์เช่นกัน
Step 6
Step 6: ตั้งชื่อ `describe()` และ `test()` ให้บอก intent ชัด
naming ที่ดีช่วยให้ debug ง่ายขึ้นมาก ชื่อ `describe()` ควรสื่อว่าเรากำลังทดสอบ unit หรือ behavior อะไร ส่วนชื่อ `test()` หรือ `it()` ควรสื่อ expected behavior ให้ชัด เช่น what should happen, when, และในเงื่อนไขไหน
ตัวอย่างนี้เปรียบเทียบชื่อที่กำกวมกับชื่อที่สื่อ expected behavior ชัดเจนกว่า
Step 7
Step 7: สรุปวิธีจำแบบสั้นที่สุด
จำแบบเร็วได้ว่า `describe()` ใช้จัดกลุ่ม, `test()` ใช้เขียน test case หนึ่งข้อ, และ `it()` คืออีกชื่อหนึ่งของ `test()` ที่เอาไว้เลือกใช้ตามสไตล์การอ่าน ถ้าคุณเริ่มเขียน test ใหม่ ให้เริ่มจาก suite หนึ่งชุดและ test case สั้น ๆ ที่บอก expected behavior ชัดเจนก่อนเสมอ