⚙️

ReactとVue3のVitestと@Storybook/test-runnerの導入比較

2024/04/24に公開

会社で以下の記事を参考に、ReactとVueそれぞれのコンポーネントライブラリのstorybookでテストができる環境を作ることになったので、必要なパッケージ、記述の違いといった部分に焦点を当てた記事です。
https://zenn.dev/cybozu_frontend/articles/update-test-libraries

最終的に目指すもの

  • npm run test or yarn testでVitestを走らせる。
  • npm run test-storybook or yarn test-storybookでstorybookのtest-runnerを動かす。

パッケージ紹介

  • @storybook/test:storybookでテストをする際に使うもので、Vitestで動いている[1]
  • @storybook/test-runner:実行するだけで全てのstoryとplay関数があればそれをテストしてくれる。
  • @testing-library/jest-dom:直感的に分かりやすい記述でDOMテストができるようになる。
  • @testing-library/react:全部は把握できていませんが、renderで簡単にコンポーネントを生成、screenでdocument.bodyに簡単にアクセス出来る。screenを使うためにはjsdomなどのglobal DOM environmentが必要らしい(把握してない)
  • @testing-library/vue:↑のVue版
  • jsdom:testing-libraryを活用するのに必要
  • vitest:これがないと始まらない

package.json

Testing LibraryがReactVue3で異なるのを除いては共通

Reactの場合

package.jsonから抜粋
{
    "devDependencies":{
        "@storybook/test": "^8.0.4",
        "@storybook/test-runner": "^0.17.0",
        "@testing-library/jest-dom": "^6.4.2",
        "@testing-library/react": "^15.0.2",
        "@vitest/ui": "^1.5.0",
        "jsdom": "^24.0.0",
        "vitest": "^1.5.0"
    },
}

Vue3の場合

package.jsonから抜粋
{
    "devDependencies":{
        "@storybook/test": "^8.0.4",
        "@storybook/test-runner": "^0.17.0",
        "@testing-library/jest-dom": "^6.4.2",
        "@testing-library/vue": "^8.0.3",
        "@vitest/ui": "^1.5.0",
        "jsdom": "^24.0.0",
        "vitest": "^1.5.0"
    },
}

vite.config.ts

ReactはdefineConfigのimport元をvitest/configにすれば良かったですが、vue3の場合はvitest.config.tsなどの別ファイルでmergeConfigを用いる必要がありました[2]

Reactの場合

vite.config.ts
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react-swc';
import path from 'path';

// https://vitejs.dev/config/
export default defineConfig({
	plugins: [react()],
	resolve: {
		alias: {
			'@': path.resolve(__dirname, './src'),
		},
	},
	test: {
		globals: true,
		environment: 'jsdom',
		setupFiles: './test/setup.ts',
		css: true
	}
});

Vue3の場合

vitest.config.ts
import { defineConfig } from "vitest/config";
import { mergeConfig } from "vite";
import viteConfig from "./vite.config";

export default mergeConfig(
  viteConfig,
  defineConfig({
    test: {
      globals: true,
      environment: "jsdom",
      setupFiles: "./test/setup.ts",
      css: true,
    },
  })
);

test.tsx/test.ts

ReactとVue3ではrenderの取り扱いが微妙に異なります。

Reactの場合

button.test.tsx
import { render, screen } from '@testing-library/react';
import { Button } from './button';

test('基本的なレンダリング', () => {
    render(<Button>ボタン</Button>); //HTML的な書き方で渡す
    expect(screen.getByRole('button')).toHaveTextContent('ボタン');
  });

Vue3の場合

button.test.ts
import Button from '../components/Button.vue';
import { render, screen } from '@testing-library/vue';

test('基本的なレンダリング', () => {
  render(Button,{
    props: {
      label: 'ボタン' //コンポーネント、Propsの順で渡す
    }
  });
  expect(screen.getByRole('button')).toHaveTextContent('ボタン');
});

# storybookのtest-runnerはどちらも同じ
脚注
  1. 元々複数のパッケージを駆使していたものを統合し便利になったものらしい ↩︎

  2. 参照 ↩︎

Discussion