Skip to content

单测与 e2e

vue3的测试主要包括三种:单测e2e类型测试。其中单测e2e都是通过配置vitest去进行测试的,配置区别只是包含不同的测试文件,基础配置都是一样的,e2e的测试都放在__tests__/e2e文件夹下。

null
json
{
  "test-unit": "vitest -c vitest.unit.config.ts",
  "test-e2e": "node scripts/build.js vue -f global -d && vitest -c vitest.e2e.config.ts"
}
{
  "test-unit": "vitest -c vitest.unit.config.ts",
  "test-e2e": "node scripts/build.js vue -f global -d && vitest -c vitest.e2e.config.ts"
}

可以看到用 e2e 测试时需要先对vue包打包成global格式,环境为dev

具体单测e2e我们就不多说了,类型测试相对有趣些,我们主要来看看是如何进行类型测试的。

类型测试

json
{
  "build-dts": "tsc -p tsconfig.build.json && rollup -c rollup.dts.config.js",
  "test-dts": "run-s build-dts test-dts-only",
  "test-dts-only": "tsc -p ./packages/dts-test/tsconfig.test.json"
}
{
  "build-dts": "tsc -p tsconfig.build.json && rollup -c rollup.dts.config.js",
  "test-dts": "run-s build-dts test-dts-only",
  "test-dts-only": "tsc -p ./packages/dts-test/tsconfig.test.json"
}

我们可以通过执行pnpm test-dts来进行类型测试,其实就是通过tsc --noEmit(配置在./packages/dts-test/tsconfig.test.json)进行类型验证,确保类型的声明是正确的。所以dts-test下的文件都是xxx.d.ts?x文件。

但在验证之前,我们需要读取(引用)到对应的类型进行测试。由于配置的moduleResolution选项是node,即会按照node的找包方式进行包的定位,当我们引入其他包类型时如import { h } from 'vue',我们会读取本地的vue/dist/vue.d.ts(在package.json.types字段指定了)去拿到对应的类型。因此我们需要通过build-dts即打包类型声明文件命令来打包类型以确保引用的类型存在

WARNING

要确保引用的类型存在,我们只需要pnpm build-dts或者pnpm build -t就可以获取所有包的类型,但是需要注意的是,如果temp/packages里不小心将不需要打包的包打包进来了,那么在执行类型打包时可能会找不到入口文件(temp/packages/<package name>/src/index.d.ts)而报错,此时只要删除掉temp文件夹重新执行pnpm build-dts或者pnpm build -t就 OK 了。

工具类型

在类型测试中,我们会用到一些工具类型来进行类似单侧断言的效果。对于预期报错的类型判断,只要加上\@ts-expect-error即可。

  • describe and test
ts
export function describe(_name: string, _fn: () => void): void
export function test(_name: string, _fn: () => any): void

describe('test h type', () => {
  test('should work', () => {
    const Foo = {
      props: {
        foo: String
      }
    }
    h(Foo, { foo: 'ok' })
  })
})
export function describe(_name: string, _fn: () => void): void
export function test(_name: string, _fn: () => any): void

describe('test h type', () => {
  test('should work', () => {
    const Foo = {
      props: {
        foo: String
      }
    }
    h(Foo, { foo: 'ok' })
  })
})

这两个函数类型只是为了能够更加语义化的进行类型测试。

  • expectType
ts
export function expectType<T>(value: T): void

expectType<number>(666)
expectType<string>(666) // throw error
export function expectType<T>(value: T): void

expectType<number>(666)
expectType<string>(666) // throw error

用来类型断言。