Files
2026-07-13 21:37:05 +08:00

3.5 KiB

测试

Vitest 配置

pnpm add -D vitest

基础配置

// vitest.config.ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    include: ['test/**/*.test.ts'],
    testTimeout: 30_000,
    reporters: 'dot',
  },
})

含覆盖率

export default defineConfig({
  test: {
    coverage: {
      provider: 'v8',
      include: ['src/**/*.ts'],
      exclude: ['src/types.ts'],
      reporter: ['text', 'lcovonly', 'html'],
    },
  },
})

工作空间项目

对于 monorepo,可以分别测试各个包:

export default defineConfig({
  test: {
    projects: [
      'packages/*/vitest.config.ts',
      {
        extends: './vitest.config.ts',
        test: { name: 'unit', environment: 'node' },
      },
      {
        extends: './vitest.config.ts',
        test: { name: 'browser', browser: { enabled: true } },
      },
    ],
  },
})

基于 Fixture 的测试

使用文件 fixture 测试转换:

import { describe, expect, it } from 'vitest'
import { transform } from '../src'

const fixtures = import.meta.glob('./fixtures/*.ts', { as: 'raw' })

describe('transform', () => {
  for (const [path, getContent] of Object.entries(fixtures)) {
    it(path, async () => {
      const content = await getContent()
      const result = await transform(content)
      expect(result).toMatchSnapshot()
    })
  }
})

幂等性测试

确保转换是稳定的:

it('transform is idempotent', async () => {
  const pass1 = (await transform(fixture))?.code ?? fixture
  expect(pass1).toMatchSnapshot()

  const pass2 = (await transform(pass1))?.code ?? pass1
  expect(pass2).toBe(pass1)  // 不应发生变化
})

类型级测试

测试 TypeScript 类型:

// vitest.config.ts
export default defineConfig({
  test: {
    typecheck: { enabled: true },
  },
})
// test/types.test-d.ts
import { describe, expectTypeOf, it } from 'vitest'
import type { Input, Output } from '../src'

describe('types', () => {
  it('infers input correctly', () => {
    expectTypeOf<Input<typeof schema>>().toEqualTypeOf<{ id: string }>()
  })
})

多 TS 版本测试

跨 TypeScript 版本测试(TanStack 模式):

# .github/workflows/ci.yml
jobs:
  test-types:
    strategy:
      matrix:
        ts: ['5.0', '5.2', '5.4', '5.6', '5.8']
    steps:
      - run: pnpm add -D typescript@${{ matrix.ts }}
      - run: pnpm typecheck

包验证

验证发布后的包:

# 检查导出是否正确
pnpm dlx publint

# 检查类型在不同 moduleResolution 下是否正常工作
pnpm dlx @arethetypeswrong/cli --pack .

添加到 tsdown 配置:

export default defineConfig({
  attw: { profile: 'esm-only' },  // 或 'node16'
})

测试脚本

{
  "scripts": {
    "test": "vitest",
    "test:run": "vitest run",
    "test:coverage": "vitest run --coverage",
    "test:types": "vitest typecheck"
  }
}

Mock

import { vi } from 'vitest'

vi.mock('fs', () => ({
  readFileSync: vi.fn(() => 'mocked content'),
}))

// 监听方法
const spy = vi.spyOn(console, 'log')
expect(spy).toHaveBeenCalledWith('expected')

测试插件

在测试中自己使用自己的插件:

// vitest.config.ts
import { defineConfig } from 'vitest/config'
import MyPlugin from './src/vite'

export default defineConfig({
  plugins: [
    MyPlugin({ /* 选项 */ }),
  ],
  test: {
    include: ['test/**/*.test.ts'],
  },
})