การทดสอบด้วย Vitest และ Testing Library
นักพัฒนา React มักจะหยิบ Jest มาใช้ร่วมกับ React Testing Library (RTL) สำหรับการทดสอบ component ตัวเทียบเท่าของ Svelte คือ Vitest + @testing-library/svelte ปรัชญาของ Testing Library นั้นเหมือนกัน — query DOM ในแบบที่ผู้ใช้ทำ, ยิง event, และ assert ผลลัพธ์ที่มองเห็นได้ API แทบจะเหมือนกันแบบ byte-for-byte ความต่างหลักอยู่ที่ test runner (Vitest เทียบกับ Jest) และวิธีการ import component (ไฟล์ .svelte เทียบกับ .tsx)
เปรียบเทียบการทดสอบ component Counter
หัวข้อที่มีชื่อว่า “เปรียบเทียบการทดสอบ component Counter”ก่อนอื่น component ที่จะนำมาทดสอบ:
// Counter.tsximport React from 'react';
export function Counter() { const [count, setCount] = React.useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(c => c + 1)}>Increment</button> </div> );}<!-- Counter.svelte --><script lang="ts"> let count = $state(0);</script><div> <p>Count: {count}</p> <button onclick={() => count++}>Increment</button></div>ทีนี้มาดูตัวทดสอบ:
// Counter.test.tsx (Jest + RTL)import { render, screen, fireEvent } from '@testing-library/react';import { Counter } from './Counter';
test('increments count', () => { render(<Counter />); expect(screen.getByText('Count: 0')).toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: 'Increment' })); expect(screen.getByText('Count: 1')).toBeInTheDocument();});// Counter.test.ts (Vitest + @testing-library/svelte)import { render, screen, fireEvent } from '@testing-library/svelte';import Counter from './Counter.svelte';import { describe, it, expect } from 'vitest';
describe('Counter', () => { it('increments count', async () => { render(Counter); expect(screen.getByText('Count: 0')).toBeInTheDocument(); await fireEvent.click( screen.getByRole('button', { name: 'Increment' }) ); expect(screen.getByText('Count: 1')).toBeInTheDocument(); });});ความต่างสำคัญที่ควรสังเกต:
- Svelte:
render(Counter)— ส่ง component class เข้าไปโดยตรง (ไม่มี JSX) ส่วน React:render(<Counter />)— เป็น JSX element - Svelte:
fireEvent.click(...)ต้องawaitเพราะ Svelte จะ batch การอัปเดต DOM แบบ asynchronous ส่วนfireEventของ React RTL เป็นแบบ synchronous - ส่วนที่เหลือทั้งหมด —
screen,getByText,getByRole,toBeInTheDocument— เหมือนกัน
การตั้งค่า Vitest
หัวข้อที่มีชื่อว่า “การตั้งค่า Vitest”import { defineConfig } from 'vitest/config';import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({ plugins: [svelte({ hot: !process.env.VITEST })], test: { environment: 'jsdom', globals: true, setupFiles: ['./src/setupTests.ts'], },});ตัวป้องกัน hot: !process.env.VITEST จะปิด HMR ระหว่างการรันทดสอบ (ซึ่งจะทำให้เกิด error ในสภาพแวดล้อม jsdom)
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”npm install --save-dev vitest @testing-library/svelte @testing-library/jest-dom jsdomสร้าง src/setupTests.ts:
import '@testing-library/jest-dom';การทดสอบ end-to-end ด้วย Playwright
หัวข้อที่มีชื่อว่า “การทดสอบ end-to-end ด้วย Playwright”Playwright ทำงานเหมือนกันทั้งกับโปรเจกต์ React และ Svelte — ไม่มีอะไรเฉพาะของ Svelte ให้ต้องเรียนรู้ ติดตั้งและตั้งค่าด้วยวิธีเดียวกัน:
npm init playwright@latest