# vue-cli をインストールする
vue-test-utils
は、VueJS 公式のテスト用ライブラリで、本ガイド全体で使用していくツールです。このツールは、ブラウザ環境でも Node.js 環境でも動作しますし、どんなテストランナーとも組み合わせることができます。本ガイドでは Node.js 環境でテストを走らせていきます。
vue-cli
は vue-test-utils
を用いたテストを始めるにあたって一番簡単な方法です。これを用いることで、プロジェクトを作成する際に、Jest の設定も行ってくれます。Jest はよく使われているテストフレームワークです。次のコマンドを実行してインストールしましょう。
yarn global add @vue/cli
npm をお使いの場合には次のコマンドを実行してください。
or with npm:
npm install -g @vue/cli
vue create [project-name]
を実行して新しいプロジェクトを作成しましょう。その際に "Manually select features" を選択し、さらに "Unit Testing" を選んで、さらにテストランナーには Jest を選択します。
インストールが終わったら、cd
でプロジェクトのディレクトリに移動し、yarn test:unit
を実行します。今までの作業がうまくいっていれば、画面に次のようにメッセージが表示されます。
PASS tests/unit/HelloWorld.spec.js
HelloWorld.vue
✓ renders props.msg when passed (26ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.074s
おめでとうございます。最初のテストを走らせて、無事テストをパスしました。
# 最初のテストを書く
さて、先ほどはプロジェクト作成時に用意されていたテストを実行しました。次に自分の手を動かしてコンポーネント書き、そのためのテストを書いていきましょう。伝統的に TDD においては、まず失敗するテストを書いて、それからテストをパスするコードを書きます。ですがまずはコンポーネントを最初に書いていくことにしましょう。
プロジェクトを作成した時に作られた src/components/HelloWorld.vue
や tests/unit/HelloWorld.spec.js
は必要ありませんので、まずはこれを消してしまいましょう。
# Greeting
component を作成する。
Greeting.vue
コンポーネントを作成していきます。このコンポーネント用のファイルは src/components
に配置します。Greeting.vue
には次のコードを書いてください。
<template>
<div>
{{ greeting }}
</div>
</template>
<script>
export default {
name: "Greeting",
data() {
return {
greeting: "Vue and TDD"
}
}
}
</script>
# テストを書く
Greeting
コンポーネントの役割はたった一つ。greeting
の値を render することだけです。ですからこのためのテストを書くには、次の方針でいきましょう。
- コンポーネントを
mount
を用いて render する。 - コンポーネントのテキスト部分に "Vue and TDD" が含まれていることを assert する。(訳注: assert とはテストにおいて、ある値がどのような値になればテストを通ったことになるか、その定義を宣言すること。)
では Greeting.spec.js
を tests/unit
ディレクトリの下に作成しましょう。そしてこのファイルの中で Greeting.vue
を import して、それから mount
をします。そうするとコードはだいたい次のようになります。
import { mount } from '@vue/test-utils'
import Greeting from '@/components/Greeting.vue'
describe('Greeting.vue', () => {
it('renders a greeting', () => {
})
})
TDD に用いられるシンタックスは様々ですが、 Jest においては describe
と it
が比較的多く使われているようです。 describe
はテストがどのようなものなのか、概要を示すために記述します。今回のケースでは Greeting.vue
という部分ですね。it
は、それによって題名を与えられたテストが、どのような目的を果たすためにあるのか、ということを示します。コンポーネントの機能が増えた際には、it
ブロックを増やしていけばいいわけです。
さて、コンポーンネントを mount
を用いて render せねばなりません。この一般的な慣習として、これによって生じたコンポーネントを wrapper
という名前の変数に紐付けます。さらにその内容を画面に出力することにしましょう。これで正常に動作しているか確認できますね。
const wrapper = mount(Greeting)
console.log(wrapper.html())
# テストを走らせる
yarn test:unit
とターミナルに打ち込んで実行することでテストを走らせましょう。tests
ディレクトリ内にある .spec.js
でファイル名が終わるものが、自動的に実行されます。全てがうまくいっていれば、以下のように画面に表示されます。
PASS tests/unit/Greeting.spec.js
Greeting.vue
✓ renders a greeting (27ms)
console.log tests/unit/Greeting.spec.js:7
<div>
Vue and TDD
</div>
先ほど書いたマークアップが正しく、テストが通ったということですね。ただし、このテストはいつでも通ります。なぜなら assertion をしていないので絶対に失敗しないからです。(それでももちろん有用ではあるのですが。) たとえ Greeting.vue
を書き換えて を削除してしまっても、このテストはパスしてしまいます。ではこれに変更を加えていきましょう。
# Assertion を作成する
コンポーネントが期待する挙動を正しくしているかどうかを判断するためには、assertion を作成する必要があります。そのためには Jest の expect
API を使用します。こんなふうにです。expect(result).to [matcher] (actual)
matcher の部分には、値やオブジェクトと比較するためのメソッドが使用されます。例えば次のようにです。
expect(1).toBe(1)
全ての matcher は Jest documentation で見ることができます。vue-test-utils
ライブラリには一切 matcher は含まれていません。Jest が提供する matcher が十分なものであるからです。Greeting
の中のテキストを比較したいので次のように書いてみましょう。
expect(wrapper.html().includes("Vue and TDD")).toBe(true)
これでも機能しますが、vue-test-utils
はマークアップを取得するための、よりよい方法を提供しています。wrapper.text
です。ではこれを使ってテストを書く作業を終わりにしましょう。
import { mount } from '@vue/test-utils'
import Greeting from '@/components/Greeting.vue'
describe('Greeting.vue', () => {
it('renders a greeting', () => {
const wrapper = mount(Greeting)
expect(wrapper.text()).toMatch("Vue and TDD")
})
})
console.log
はもう必要ないので削除してしまってもかまいません。yarn test:unit
を実行してテストを走らせましょう。全てがうまくいっていれば、次のようになるはずです。
PASS tests/unit/Greeting.spec.js
Greeting.vue
✓ renders a greeting (15ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.477s, estimated 2s
よさそうですね。ですが、TDD の伝統に則るのであれば、まずテストが失敗するところから初めて、次にそれが通るようにするという手順を踏んで、本当に機能していることを確認したほうがいいでしょう。テストをまず書いてから、そのあとに実装をします。そしてテストが失敗したら、そのエラー文を参考にコードを修正していきます。ではそうなるようにやってみましょう。すでに書いた Greeting.vue
コンポーネントを次のように変更します。
<template>
<div>
{{ greeting }}
</div>
</template>
<script>
export default {
name: "Greeting",
data() {
return {
greeting: "Vue without TDD"
}
}
}
</script>
そして yarn test:unit
で実行します。
FAIL tests/unit/Greeting.spec.js
Greeting.vue
✕ renders a greeting (24ms)
● Greeting.vue › renders a greeting
expect(received).toMatch(expected)
Expected value to match:
"Vue and TDD"
Received:
"Vue without TDD"
6 | const wrapper = mount(Greeting)
7 |
> 8 | expect(wrapper.text()).toMatch("Vue and TDD")
| ^
9 | })
10 | })
11 |
at Object.<anonymous> (tests/unit/Greeting.spec.js:8:28)
エラーに関するフィードバックを得ることができました。期待する値と、テスト実行時の実際の値がわかりますね。そしてどの行でエラーが出ているかも示されています。テストは失敗しました。これは私たちが予想していた通りです。Greeting.vue
を元に戻して、テストがもう一度通るようにしましょう。
次は vue-test-utils
が提供する、コンポーネントをレンダーするためのメソッドである mount
と shallowMount
についてみていきましょう。
← ようこそ コンポーネントをレンダー →