Open3

JestからVitestへ移行したときに気付いたこと

はじめに

JestからVitestに移行した
このスクラップでは移行の際に気づいたことをまとめる。
(Jestと互換性のあるAPIでめっちゃスムーズに移行できた)

https://vitest.dev/

検証環境

実際に移行したプロダクトは載せられないので再現できる似たような環境を用意した。
Node: 16.13.2

検証用Repository

https://github.com/wattanx/vitest-sample

下記は一部

package.json
{
  "devDependencies": {
    "@babel/preset-env": "^7.16.11",
    "@vue/test-utils": "^1.2.2",
    "babel-core": "^7.0.0-bridge.0",
    "babel-jest": "^27.0.6",
    "jest": "^27.0.4",
    "jsdom": "^19.0.0",
    "ts-jest": "^27.0.4",
    "typescript": "^4.3.5",
    "vite": "^2.8.3",
    "vite-plugin-vue2": "^1.7.3",
    "vitest": "^0.3.5",
    "vue": "^2.6.14",
    "vue-jest": "^3.0.7",
    "vue-template-compiler": "^2.6.14"
  }
}

やったこと

前提

  • Viteを利用している。(vite.config.tsがすでに存在している)
  • Jestを使ってTestが書かれている。

移行の際にやったこと

  • Jestで一旦テスト時間の計測
  • Vitestのinstall & Viteのバージョンアップ
  • vite.config.tsに下記の項目を追加。
vite.config.ts
+ /// <reference types="vitest" />
import { defineConfig } from "vite";
import { createVuePlugin } from "vite-plugin-vue2";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [createVuePlugin()],
+ test: {
+   globals: true,
+   environment: "jsdom",
+ },
});
  • jest.fn()などのjestviに変更
  • テストが通るように修正。
  • Vitestによるテストの時間を計測

Componentのレンダリング時にscoped cssの識別子が付与される。

テスト対象のコンポーネント

slotの内容をCenter寄せにするComponent(適当なComponent)

Center.vue
<template>
  <div class="center"><slot name="text" /></div>
</template>

<script lang="ts">
import { defineComponent } from "@vue/composition-api";

export default defineComponent({
  name: "Center",
});
</script>

<style scoped>
.center {
  text-align: center;
  margin-left: auto;
  margin-right: auto;
}
</style>

Test

slotの内容が表示されるかどうか確認するTestを下記のように記述する。
下記のTestはVitestでは通らない。

Center.spec.ts
import { mount } from "@vue/test-utils";
import Center from "../components/Center.vue";

describe("Center Test", () => {
  it("slotの内容が描画されること", () => {
    const wrapper = mount(Center, {
      slots: {
        text: "<p>test</p>",
      },
    });
    expect(wrapper.html()).toContain("<p>test</p>");
  });
});

JestではComponentが下記のようにレンダリングされ、Testは通る。

<div class="center">
  <p>test</p>
</div>

ただし、Vitestで実行した場合下記のようにレンダリングされるのでテストが通らない。

<div data-v-31414005="" class="center">
  <p data-v-31414005="">test</p>
</div>

Jestで実行時はtransformerにvue-jestを利用しており、下記の実装をみるとscoped: falseになっている。そのため、vue-jestでは識別子がついてなさそう。

https://github.com/vuejs/vue-jest/blob/master/packages/vue2-jest/lib/process-style.js#L99

Vitestで実行時は、vite-plugin-vue2を使っていて、アプリケーション側と同じようにレンダリングされるため識別子が付与されてそう。(vite.config.tsはアプリケーション側、テスト側共通なので)

https://github.com/underfin/vite-plugin-vue2/blob/master/src/style.ts#L19
ログインするとコメントできます