Dark mode
Next Generation Testing Framework
Introduction
Vitest เป็นเฟรมเวิร์กสำหรับการทดสอบแบบหน่วย (unit testing) ที่ทำงานร่วมกับ Vite ได้อย่างมีประสิทธิภาพ เหมาะสำหรับโปรเจ็กต์ JavaScript และ TypeScript Vitest เป็นกรอบการทดสอบหน่วยที่เร็วมาก ใช้พลังจาก Vite ให้โซลูชันการทดสอบที่สมบูรณ์ด้วย:
- โหมดดูแบบทันที
- รองรับ ESM, TypeScript และ JSX ทันที
- การทำงานหลายเธรดผ่าน workers
- การกรอง การกำหนดเวลา และการทำงานพร้อมกันสำหรับชุดทดสอบ
Comparison
ข้อแตกต่างระหว่างเฟรมเวิร์กการทดสอบที่นิยม
คุณสมบัติ | |||
---|---|---|---|
ความเร็ว | ⚡ เร็วมาก (ใช้ Vite) | 🐢 ปานกลาง | ⚡ เร็ว |
HMR | ✅ ในตัว | ❌ ไม่มี | ✅ ในตัว |
ESM Support | ✅ ในตัว | ❌ ต้องกำหนดค่า | ✅ ในตัว |
TypeScript | ✅ ในตัว | ❌ ต้องใช้ ts-jest | ✅ ในตัว |
Browser Testing | ✅ ผ่าน Playwright | ❌ ต้องใช้ Puppeteer | ❌ ไม่มี |
Snapshot Testing | ✅ ในตัว | ✅ ในตัว | ❌ ไม่มี |
Parallel Testing | ✅ ในตัว | ✅ ในตัว | ✅ ในตัว |
Mocking | ✅ vi ในตัว | ✅ jest ในตัว | ✅ ในตัว |
Coverage | ✅ ในตัว | ✅ ในตัว | ❌ ต้องใช้ nyc |
Installation
ขั้นตอนการติดตั้ง Vitest ในโปรเจ็กต์ของคุณด้วย package managers ต่างๆ
bash
npm install -D vitest
bash
pnpm add -D vitest
bash
yarn add -D vitest
bash
bun add -D vitest
Configuration
การตั้งค่า Vitest ผ่านไฟล์ config เพื่อปรับแต่งการทำงาน
สร้าง vitest.config.ts
:
ts
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// เปิดใช้งาน global APIs เหมือนใน Jest
globals: true,
// สภาพแวดล้อมสำหรับทดสอบ DOM (จำเป็นสำหรับคอมโพเนนท์)
environment: "jsdom",
coverage: {
// ใช้ istanbul สำหรับรายงาน coverage
provider: "istanbul",
},
},
});
Configuration Options
การตั้งค่าพื้นฐานสำหรับการกำหนดค่า Vitest Basic settings to configure how Vitest runs your tests.
Core Settings
การตั้งค่าพื้นฐานเกี่ยวกับสภาพแวดล้อมการทดสอบและการรวมไฟล์ Fundamental configurations that affect test environment and file inclusion.
ตัวเลือก | คำอธิบาย | ตัวอย่าง |
---|---|---|
globals | เปิดใช้งาน API ระดับ global เช่นเดียวกับใน Jest | globals: true |
environment | กำหนดสภาพแวดล้อมการทดสอบ (node, jsdom, happy-dom) | environment: 'jsdom' |
include | รายการไฟล์ที่จะรวมในการทดสอบ | include: ['**/*.test.ts'] |
exclude | รายการไฟล์ที่จะยกเว้นจากการทดสอบ | exclude: ['node_modules'] |
alias | กำหนด path aliases เหมือนใน Vite | alias: { '@': path.resolve(__dirname, './src') } |
root | กำหนด root directory ของโปรเจ็กต์ | root: './src' |
Test Execution
การตั้งค่าการทำงานของเทส เช่น การจำกัดเวลาและการรันแบบขนาน Settings that control how tests are run, including timeouts and parallel execution.
ตัวเลือก | คำอธิบาย | ตัวอย่าง |
---|---|---|
testTimeout | ระยะเวลาสูงสุดที่อนุญาตให้การทดสอบทำงาน (มิลลิวินาที) | testTimeout: 10000 |
threads | เปิด/ปิดการรันเทสแบบขนาน | threads: false |
isolate | แยก environment สำหรับแต่ละไฟล์ทดสอบ | isolate: true |
passWithNoTests | ผ่านแม้ไม่มีเทสที่รันได้ | passWithNoTests: true |
retry | จำนวนครั้งที่จะลองรันเทสที่ล้มเหลว | retry: 2 |
Reporting
การตั้งค่ารูปแบบการแสดงผลและรายงานผลการทดสอบ Options for configuring test output and reporting formats.
ตัวเลือก | คำอธิบาย | ตัวอย่าง |
---|---|---|
reporters | รูปแบบการแสดงผลการทดสอบ | reporters: ['default', 'json'] |
outputFile | บันทึกผลลัพธ์ลงไฟล์ | outputFile: './test-results.json' |
silent | ปิดการแสดงผลใน console | silent: true |
logHeapUsage | แสดงการใช้หน่วยความจำ | logHeapUsage: true |
Coverage
การตั้งค่าการวัดความครอบคลุมของโค้ด Configuration for code coverage analysis and reporting.
ตัวเลือก | คำอธิบาย | ตัวอย่าง |
---|---|---|
coverage.provider | ระบบสร้างรายงาน coverage (istanbul หรือ v8) | provider: 'istanbul' |
coverage.enabled | เปิดใช้งาน coverage โดยอัตโนมัติ | enabled: true |
coverage.reporter | รูปแบบรายงาน coverage | reporter: ['text', 'html'] |
coverage.thresholds | กำหนดค่า coverage ขั้นต่ำ | thresholds: { lines: 80 } |
Features
แนวคิดหลักที่ควรเข้าใจเมื่อทำงานกับ Vitest
Concept | คำอธิบาย | ตัวอย่าง |
---|---|---|
รันแบบติดตามการเปลี่ยนแปลงอัตโนมัติ | vitest หรือ vitest watch | |
รันเฉพาะบางการทดสอบ | vitest test my-test | |
รันหลายการทดสอบพร้อมกัน | it.concurrent() | |
สร้างฟังก์ชันจำลอง | const mock = vi.fn() | |
ตรวจสอบผลลัพธ์กับค่าที่บันทึกไว้ | expect(result).toMatchSnapshot() | |
วัดโค้ดที่ยังไม่ได้ทดสอบ | vitest run --coverage | |
เขียนเทสในไฟล์เดียวกันกับโค้ด | if (import.meta.vitest) { ... } | |
ทดสอบประเภทข้อมูล | expectTypeOf(1).toBeNumber() |
CLI Commands
คำสั่งสำคัญสำหรับการทำงานกับ Vitest
Command | คำอธิบาย | ตัวเลือก |
---|---|---|
vitest | รันการทดสอบในโหมด watch (ติดตามการเปลี่ยนแปลง) | --ui , --coverage |
vitest run | รันการทดสอบครั้งเดียว | --reporter , --threads |
vitest watch | รันและติดตามการเปลี่ยนแปลงไฟล์ | --ignore |
vitest dev | รันการทดสอบในโหมดพัฒนา | --api |
vitest related | รันเฉพาะการทดสอบที่เกี่ยวข้องกับไฟล์ที่แก้ไข | --changed |
vitest bench | รันการทดสอบประสิทธิภาพ | --watch |
vitest init | สร้างไฟล์ config เริ่มต้น | --force |
vitest list | แสดงรายการการทดสอบทั้งหมด | --verbose |
APIs
Test API Reference
Test API Reference คือชุดคำสั่งสำหรับการเขียนการทดสอบใน Vitest โดยมีคำสั่งหลักๆ ดังนี้
API | คำอธิบาย | ตัวอย่าง |
---|---|---|
test() | กำหนดการทดสอบ | test('description', () => { ... }) |
describe() | กลุ่มการทดสอบ | describe('feature', () => { ... }) |
beforeAll() | เรียกก่อนทุกการทดสอบ | beforeAll(() => setup()) |
afterAll() | เรียกหลังทุกการทดสอบ | afterAll(() => cleanup()) |
beforeEach() | เรียกก่อนแต่ละการทดสอบ | beforeEach(() => init()) |
afterEach() | เรียกหลังแต่ละการทดสอบ | afterEach(() => reset()) |
onTestFinished() | เรียกเมื่อการทดสอบเสร็จสิ้น | onTestFinished(() => cleanup()) |
onTestFailed() | เรียกเมื่อการทดสอบล้มเหลว | onTestFailed(({ task }) => log(task)) |
Mock Functions
Mock Functions ช่วยให้คุณสร้างและจัดการฟังก์ชันจำลอง (mock functions) สำหรับทดสอบ โดยสามารถกำหนดพฤติกรรมและตรวจสอบการเรียกใช้ได้
Method/Property | คำอธิบาย | ตัวอย่าง |
---|---|---|
mockImplementation() | กำหนดการทำงานของ mock function | mock.mockImplementation(() => 'value') |
mockImplementationOnce() | กำหนดการทำงานของ mock function แบบครั้งเดียว | mock.mockImplementationOnce(() => 'once') |
mockReturnValue() | กำหนดค่าที่จะ return | mock.mockReturnValue(42) |
mockReturnValueOnce() | กำหนดค่าที่จะ return แบบครั้งเดียว | mock.mockReturnValueOnce(1) |
mockResolvedValue() | กำหนดค่าที่จะ resolve สำหรับ async function | mock.mockResolvedValue('data') |
mockResolvedValueOnce() | กำหนดค่าที่จะ resolve แบบครั้งเดียว | mock.mockResolvedValueOnce('temp') |
mockRejectedValue() | กำหนดค่าที่จะ reject สำหรับ async function | mock.mockRejectedValue(new Error()) |
mockClear() | ล้างประวัติการเรียกใช้ | mock.mockClear() |
mockReset() | ล้างประวัติและรีเซ็ตการทำงาน | mock.mockReset() |
mockRestore() | คืนค่า function เดิม | mock.mockRestore() |
mock.calls | อาร์เรย์ของทุกการเรียกใช้ | mock.mock.calls |
mock.results | อาร์เรย์ของทุกผลลัพธ์ | mock.mock.results |
mock.contexts | อาร์เรย์ของ context this | mock.mock.contexts |
mock.instances | อาร์เรย์ของ instances | mock.mock.instances |
Vi Utility
Utility functions สำหรับจัดการ timers, globals และ mock ทั้งหมดใน Vitest
API | คำอธิบาย | ตัวอย่าง |
---|---|---|
vi.useFakeTimers() | mock timer functions | vi.useFakeTimers() |
vi.stubGlobal() | mock global variables | vi.stubGlobal('fetch', mockFetch) |
vi.clearAllMocks() | ล้าง mock ทั้งหมด | vi.clearAllMocks() |
vi.useRealTimers() | เรียกใช้ timer จริง | vi.useRealTimers() |
vi.advanceTimersByTime() | เลื่อนเวลาใน fake timers | vi.advanceTimersByTime(1000) |
vi.runAllTimers() | รัน timer ทั้งหมดที่ pending | vi.runAllTimers() |
vi.setSystemTime() | ตั้งค่าเวลาในระบบ | vi.setSystemTime(new Date(2023, 0, 1)) |
Expect
Assertion functions สำหรับตรวจสอบผลลัพธ์ที่คาดหวังในการทดสอบ
API | คำอธิบาย | ตัวอย่าง |
---|---|---|
expect() | ตรวจสอบผลลัพธ์ | expect(value).toBe(3) |
.toBe() | ตรวจสอบความเท่ากัน | expect(1 + 1).toBe(2) |
.toEqual() | ตรวจสอบ object/array | expect(obj).toEqual({key: value}) |
.toMatch() | ตรวจสอบ string ด้วย regex | expect('hello').toMatch(/llo/) |
.toContain() | ตรวจสอบ array/string มีค่าที่ต้องการ | expect([1,2]).toContain(1) |
.toBeTruthy() | ตรวจสอบค่า truthy | expect('hello').toBeTruthy() |
.toBeFalsy() | ตรวจสอบค่า falsy | expect('').toBeFalsy() |
.toBeDefined() | ตรวจสอบค่า defined | expect(var).toBeDefined() |
.toBeUndefined() | ตรวจสอบค่า undefined | expect(undefined).toBeUndefined() |
.toBeNull() | ตรวจสอบค่า null | expect(null).toBeNull() |
ExpectTypeOf
Assertion functions เฉพาะสำหรับตรวจสอบประเภทข้อมูล TypeScript
API | คำอธิบาย | ตัวอย่าง |
---|---|---|
expectTypeOf() | ตรวจสอบ type | expectTypeOf(1).toBeNumber() |
.toBeNumber() | ตรวจสอบ type number | expectTypeOf(1).toBeNumber() |
.toBeString() | ตรวจสอบ type string | expectTypeOf('a').toBeString() |
.toBeBoolean() | ตรวจสอบ type boolean | expectTypeOf(true).toBeBoolean() |
.toBeSymbol() | ตรวจสอบ type symbol | expectTypeOf(Symbol()).toBeSymbol() |
.toBeNull() | ตรวจสอบ type null | expectTypeOf(null).toBeNull() |
.toBeUndefined() | ตรวจสอบ type undefined | expectTypeOf(undefined).toBeUndefined() |
.toBeArray() | ตรวจสอบ type array | expectTypeOf([]).toBeArray() |
.toBeFunction() | ตรวจสอบ type function | expectTypeOf(() => {}).toBeFunction() |
.toBeObject() | ตรวจสอบ type object | expectTypeOf({}).toBeObject() |
.toHaveProperty() | ตรวจสอบ property ของ object | expectTypeOf({a:1}).toHaveProperty('a') |
Assert
Assertion functions แบบดั้งเดิม (เหมือนกับใน Node.js assert module)
API | คำอธิบาย | ตัวอย่าง |
---|---|---|
assert() | assertion แบบดั้งเดิม | assert(true) |
assert.equal() | ตรวจสอบความเท่ากัน | assert.equal(1, 1) |
assert.isTrue() | ตรวจสอบค่า true | assert.isTrue(true) |
assert.isFalse() | ตรวจสอบค่า false | assert.isFalse(false) |
assert.isExtensible() | ตรวจสอบ object ที่สามารถเพิ่ม property | assert.isExtensible({}) |
assert.isNotExtensible() | ตรวจสอบ object ที่ไม่สามารถเพิ่ม property | assert.isNotExtensible(Object.preventExtensions({})) |
assert.isSealed() | ตรวจสอบ sealed object | assert.isSealed(Object.seal({})) |
assert.isFrozen() | ตรวจสอบ frozen object | assert.isFrozen(Object.freeze({})) |
assert.isEmpty() | ตรวจสอบค่าว่าง | assert.isEmpty([]) |
assert.isNotEmpty() | ตรวจสอบค่าไม่ว่าง | assert.isNotEmpty([1]) |
AssertType
Assertion functions สำหรับตรวจสอบประเภทข้อมูล TypeScript แบบ low-level
API | คำอธิบาย | ตัวอย่าง |
---|---|---|
assertType() | ตรวจสอบ type ใน compile-time | assertType<string>('test') |
assertType<T>() | ตรวจสอบ generic type | assertType<number>(1) |
Examples
Basic Test Example
ts
import { describe, expect, it } from "vitest";
// describe: ใช้จัดกลุ่ม test case ที่เกี่ยวข้องกัน
// it: ใช้กำหนดแต่ละ test case
// expect: ใช้เขียน assertions
describe("basic math", () => {
it("adds two numbers", () => {
expect(1 + 1).toBe(2);
});
it("subtracts numbers", () => {
expect(5 - 3).toBe(2);
});
});
File System Testing
ts
import { existsSync, readFileSync } from "fs";
import { describe, expect, it } from "vitest";
// existsSync: ตรวจสอบว่ามีไฟล์อยู่หรือไม่
// readFileSync: อ่านเนื้อหาไฟล์แบบ synchronous
describe("file operations", () => {
it("checks if file exists", () => {
expect(existsSync("./package.json")).toBe(true);
});
it("reads file content", () => {
const content = readFileSync("./package.json", "utf-8");
expect(content).toContain("\"name\"");
expect(content).toContain("\"version\"");
});
});
Component Testing (Vue)
ts
import { mount } from "@vue/test-utils";
import { describe, expect, it } from "vitest";
import MyComponent from "./MyComponent.vue";
describe("MyComponent", () => {
it("renders correctly", () => {
const wrapper = mount(MyComponent, {
props: { msg: "Hello Vitest" },
});
expect(wrapper.text()).toContain("Hello Vitest");
});
});
Testing File Upload (Mocking)
ts
import { describe, expect, it, vi } from "vitest";
import { uploadFile } from "./file-utils";
// สร้าง mock file object
// File constructor: สร้าง object ที่เลียนแบบไฟล์จริง
const mockFile = new File(["content"], "test.txt", { type: "text/plain" });
// ตัวอย่างการทดสอบ file upload
// vi.fn(): mock fetch API
// mockResolvedValue: กำหนด response ที่ต้องการ
describe("file upload", () => {
it("uploads file successfully", async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ success: true }),
});
const result = await uploadFile(mockFile);
// ตรวจสอบว่าอัพโหลดสำเร็จ
expect(result.success).toBe(true);
// ตรวจสอบว่าเรียก fetch
expect(fetch).toHaveBeenCalled();
});
});