Vue.jsでUIコンポーネントをテストする方法について確認します。「UIコンポーネントのテストで確認すべきこと」「vue-test-utils」について取り上げています。
環境
Vue CLI
で動作確認用のプロジェクトを構築しています。
$ vue create vue-component-test
Vue CLI v3.4.1
┌───────────────────────────┐
│ Update available: 3.5.0 │
└───────────────────────────┘
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Router, Vuex, CSS Pre-processors, Linter, Unit, E2E
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript for auto-detected polyfills? Yes
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Stylus
? Pick a linter / formatter config: TSLint
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lint on save
? Pick a unit testing solution: Jest
? Pick a E2E testing solution: Cypress
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
Unit Testing
を選択したため、vue-test-utils
もインストール済みです。
ユニットテストツールには Jest
を選択しています。
vue-test-utilsでShallow描画
Vue CLI
で構築したプロジェクトには、すでに以下テスト( tests/unit/example.spec.ts
)が作成されていました。
import { shallowMount } from '@vue/test-utils';
import HelloWorld from '@/components/HelloWorld.vue';
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message';
const wrapper = shallowMount(HelloWorld, {
propsData: { msg },
});
expect(wrapper.text()).toMatch(msg);
});
});
HelloWorldコンポーネント
を Shallow描画
してテストしているようです。
テストの実行
yarn test:unit
でユニットテストを実行できます。
--watchオプション
もあるようです。
$ yarn test:unit --help
yarn run v1.13.0
$ vue-cli-service test:unit --help
Usage: vue-cli-service test:unit [options] <regexForTestFiles>
Options:
--watch run tests in watch mode
All jest command line options are supported.
See https://facebook.github.io/jest/docs/en/cli.html for more details.
✨ Done in 0.46s.
テストで確認すること
vue-test-utils のドキュメントでは、ホワイトボックスなテスト
よりも ブラックボックスなテスト
が推奨されているようでした。コンポーネント内にどんなメソッドがあるのかは関知せずに、主に以下のことを検証すれば良いかと思います。
- propsに値を渡して、期待した動きになっていること
- ユーザー操作によって、イベントが発火されて、期待した動きになっていること
例
テストコンポーネント
例として、下記コンポーネントをテストしてみます。
<template>
<div
@click="click"
:class="{ outline: outline }">
<slot></slot>
</div>
</template>
<script>
export default {
props: {
outline: {
type: Boolean,
default: false,
},
},
methods: {
click() {
this.$emit('click');
},
},
};
</script>
テストコード
import {shallowMount} from '@vue/test-utils';
import Btn from '@/components/Btn.vue';
describe('Btn.vue', () => {
describe('props', () => {
it('does not have the outline class', () => {
const wrapper = shallowMount(Btn);
expect(wrapper.classes()).not.toContain('outline')
});
it('has the outline class', () => {
const wrapper = shallowMount(Btn, {
propsData: {outline: true},
});
expect(wrapper.classes()).toContain('outline')
});
});
describe('event', () => {
it('click event is executed', () => {
const wrapper = shallowMount(Btn);
wrapper.trigger('click');
expect(wrapper.emitted().click).toBeTruthy();
});
})
});
propsに値を渡しての確認
と ユーザー操作の確認
で describe
を分けています。
テスト実行
テストを実行してみます。
$ yarn test:unit tests/unit/btn.spec.ts
yarn run v1.13.0
$ vue-cli-service test:unit tests/unit/btn.spec.ts
PASS tests/unit/btn.spec.ts
Btn.vue
props
✓ does not have the outline class (17ms)
✓ has the outline class (2ms)
event
✓ click event is executed (4ms)
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 3.72s
Ran all test suites matching /tests\/unit\/btn.spec.ts/i.
✨ Done in 5.35s.
参考
- https://jp.vuejs.org/v2/guide/unit-testing.html
- https://vue-test-utils.vuejs.org/ja/
- テストの検証に利用できるメソッドの確認は、以下ページで確認すれば良さそうです。