เริ่มต้นด้วยการทำความรู้จักโครงสร้างของการเขียน unit testing กันก่อนเลย
ใน jest และ test library ของภาษาอื่นๆ นั้นจะคล้ายๆ กัน โดยมีโครงสร้างแบบนี้
test('two plus two is four', () => {
expect(2 + 2).toBe(4)
})
single test
หากว่ามีหลายๆ test แล้วต้องการจัดกลุ่มให้มัน เราจะใช้ describe
describe('Math function', () => {
test('two plus two is four', () => {
expect(2 + 2).toBe(4)
})
test('two multiply two is four', () => {
expect(2 * 2).toBe(4)
})
})
grouping test with describe
โครงสร้างการเขียน test
ในการเขียน test นั้น แนะนำให้ใช้สิ่งที่เรียกว่า 3A คือ
- Arrange: การเตรียมการก่อนเริ่มทดสอบ
- Action: การเรียกใช้งาน Function หรือ การทำอะไรสักอย่าง เพื่อให้ได้ผลการทดสอบ
- Assert: การตรวจสอบความถูกต้อง
หน้าตามันเป็นแบบนี้
import { add } from "../src/math"
it('message', () => {
// Arrange
const num1 = 5
const num2 = 3
const actual = 8
// Action
const result = add(num1, num2)
// Assert
expect(result).toEqual(actual)
})
3A
การทดสอบแบบ Asynchronous
เป็นเรื่องปกติใน JavaScript โค้ดที่เราเขียน จะมีการทำงานแบบ asynchronous และเมื่อโค้ดของเรามีการทำงานแบบ asynchronous ตัว jest จำเป็นต้องรู้ว่าโค้ดที่กำลังทดสอบเสร็จสมบูรณ์เมื่อไหร่ ก่อนที่จะสามารถไปยังการทดสอบอื่นได้
โดย Jest มีหลายวิธีในการจัดการเรื่องนี้
Promises
การ return ค่า แบบ promise ภายใน code ของเรา jest จะรอให้ promise นั้น resolve ก่อน แต่ถ้าหากมีการ rejected จาก promise เท่ากับว่าการทดสอบนั้นล้มเหลว
test('the data is peanut butter', () => {
return fetchData().then((data) => {
expect(data).toBe('peanut butter')
})
})
promise resolve
หากเราต้องการทดสอบ reject
ของ promise ให้ใช้วิธี .catch
test('the fetch fails with an error', () => {
expect.assertions(1)
return fetchData().catch((error) => {
expect(error).toMatch('error messages')
})
})
promise reject
expect.assertions
ใส่เข้ามาเพื่อตรวจสอบว่า มีการเรียกการเรียกใช้งานจริงๆ หากเราไม่ได้ใส่มันเข้าไปด้วย การทดสอบมันจะไม่ fail
Async/Await
เราสามารถใช้ async
และ await
ในการทดสอบของเราได้ หากต้องการเขียนการทดสอบแบบ async ให้ใช้คีย์เวิร์ด async
หน้าฟังก์ชันที่ผ่านการทดสอบ
ตัวอย่าง เช่น สถานการณ์จำลอง fetchData
เดียวกัน สามารถทดสอบได้ด้วย:
test('the data is peanut butter', async () => {
const data = await fetchData()
expect(data).toBe('peanut butter')
})
test('the fetch fails with an error', async () => {
expect.assertions(1)
try {
await fetchData()
} catch (error) {
expect(error).toMatch('error')
}
})
async/await with try catch
expect.assertions(1)
ใช้เพื่อตรวจาสอบว่า assertions ถูกเรียกหรือเปล่า
หรือ เราสามารถรวม async
และ await
กับ .resolves
หรือ .rejects
ก็ได้
test('the data is peanut butter', async () => {
await expect(fetchData()).resolves.toBe('peanut butter')
})
test('the fetch fails with an error', async () => {
await expect(fetchData()).rejects.toMatch('error')
})
async/await with resolve & reject
Callbacks
ถ้าหากเราต้องการทดสอบ function ที่มีการใช้ callback นั้น ก็สามารถ ใช้งานได้ ดังนี้
test('the data is peanut butter', (done) => {
function callback(error: string | null, data: string | null) {
if (error) {
done(error)
return
}
try {
expect(data).toBe('peanut butter')
done()
} catch (error) {
done(error)
}
}
fetchDataWithCallback(callback)
})
testing with callback function