基礎からわかる、Vue.jsのテスト 第1回 テスト環境の構築

シリーズ第1回目ではVueのコンポーネントをテストする環境を整えます。そしてシンプルな構成のVueファイルに対してテストを行ってみましょう。まずはざっと概要を把握することが大切です。

発行

著者 中島 直博 フロントエンド・エンジニア
基礎からわかる、Vue.jsのテスト シリーズの記事一覧

はじめに

Vue.jsを使った開発では、機能や役割に合わせて「コンポーネント」という単位でアプリケーションの開発を進めます。Vue.jsは、SingleFileComponent(以下SFC)と呼ばれる形式で、1つのファイル(.vue)にJavaScript、HTML、CSSをまとめる形でコンポーネントを作成できます。これをVueコンポーネントと呼ぶこともあります。

VueコンポーネントのようなデータとUIを伴う形式のコンポーネントは「UIコンポーネント」と分類され、テストの方法もJavaScriptだけを対象としたテスト*とは異なる方法が必要です。

*注:JavaScriptのテスト

JavaScriptのユニットテストに関しては実践、ユニットテストJavaScript開発のためのテスト入門などのシリーズで解説しています。

Vueコンポーネントの振る舞いは、コンポーネントに与えるpropsや自身のdata、それに影響されるcomputedプロパティ、methodsの呼び出しなど、さまざま状態や状況によって変わります。それらのデータはtemplateによってレンダリングされ、DOMイベントと協調したり、カスタムイベントでコンポーネント同士がやり取りしたりなど、多くの要素が絡んできます。

本シリーズでは、Vueのコンポーネントの振る舞いを保証または確認するために、何をどのような方法でテストしていくかを解説します。

以降で紹介するサンプルコードは、次のリポジトリからダウンロード、またはクローンできます。併せて参照してください。

基礎からわかる、Vue.jsのテストリポジトリ

前提条件

本シリーズは次の条件を想定して書かれています。

  • .vueファイルによる開発
  • Node.js v7.6.x以上

.vueファイルによる開発はvue-cliを使ってvuejs-templates/webpackvuejs-templates/webpack-simplenuxt-community/starter-templateなどのテンプレートを利用している環境を想定しています。

Node.jsのバージョンは、async/awaitが使えるバージョンを想定しています。

Vueプロジェクトの作成

テストを追加するプロジェクトを作成します。既存のプロジェクトにテストを追加する場合は、この節を飛ばして次に進んでください。

vue-cliでプロジェクトを作成する

vue-cliを使って、webpackを使ったシンプルな構成のプロジェクトを作成します。

まずnpmからvue-cliをグローバルにインストールします。

npm install -g vue-cli

次にプロジェクトの初期化を行います。

vue init webpack-simple test_project

これでプロジェクトが作成できました。このプロジェクトにテストを実行するための環境を整えていきます。

npm 5.2.0以上の場合はnpxが使えます

npmのバージョンが5.2.0以上のものを使っている場合、npxコマンドで、vue-cliのインストールとプロジェクトの作成を同時に行えます。

npx vue-cli init webpack-simple test_project

コンポーネントのテストの例

テストの環境を整える前に、実際のテストケースがどのようなものか見てみましょう。

まずはコンポーネントのコードです。

MyComponent.vue

<template>
  <div>
    {{text}}
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  props: {
    text: String,
  },
}
</script>

このコンポーネントはpropsで受け取ったtextを表示するだけの単純なものです。次のような使われ方をします。

<template>
  <div>
    <h1>すごいアプリ</h1>
    <MyComponent text="すごいテキスト" />
  </div>
</template>

このコンポーネントに対して、次のような項目のテストケースを書きます。

  • propsが受け取れることを確認する
  • propsで受け取った内容がレンダリングされるか確認する

これらの項目に対応するテストのコードは次のとおりです。

MyComponent.test.js

import {shallow} from '@vue/test-utils'
import MyComponent from './MyComponent.vue'
describe('MyComponent.vue', () => {
  let wrapper
  beforeEach(() => {
    wrapper = shallow(MyComponent)
  })

  describe('props', () => {
    test('propsが受け取れること', () => {
      wrapper.setProps({
        text: 'hello test',
      })
      expect(wrapper.props().text).toBe('hello test')
    })
  })

  describe('template', () => {
    test('textがレンダリングされること', () => {
      wrapper.setProps({
        text: 'hello test',
      })
      expect(wrapper.text()).toBe('hello test')
    })
  })
})

このコンポーネントはテキストを表示するだけの単純なものですが、実際のプロジェクトではもう少し機能を持ったコンポーネントを作ることになります。

書き方さえ知ってしまえば、テストケースを書くのは難しいことではありません。コンポーネントに応じたテストが書けるように、本シリーズで順番に覚えていきましょう。

テストに利用するパッケージ

Vueコンポーネントのテストには主に次の2つを利用します。

vue-test-utilsはVue.jsの公式が提供している、Vueコンポーネントをテストするための専用ユーティリティライブラリです。Vueコンポーネントのコンパイル、コンポーネントのスタブ化やモックの注入など、テストに必要な機能を提供しています。本シリーズではこのvue-test-utilsの使い方を中心に解説していきます。

Jestはテストを実行するためのテストランナーです。上述したテストの例にあるようなdescribeexpectといった機能はJestが用意しているものです。テストに必要な機能のほとんどを備えていることもあり、テストを始めるには最適なテストランナーです。JestについてはJestで始める! ユニットテストのシリーズに解説があります。

補足:Jest以外のテストランナーも使えます

vue-test-utils自体にはテストランナーへの依存がないので、Mochaなど、ほかのテストランナーでもVueコンポーネントのテストは行えます。vue-test-utilsのページには、ほかのテストランナーで動かすサンプルがいくつかあるので、参考にしてみてください。

パッケージのインストール

テストの実行に必要なパッケージをインストールしましょう。インストールするのは次の4つです。

  • @vue/test-utils (v1.0.0-beta.11)
  • jest (v22.2.1)
  • babel-jest (v22.2.0)
  • vue-jest (v2.0.1)

注:()内のバージョンと必須パッケージについて

()内のバージョンは執筆時点のものです。また、もしテストを実行するプロジェクトに次のパッケージがインストールされていない場合、別途インストールが必要になります。

  • vue
  • vue-template-compiler
  • babel-preset-env

これらのパッケージは、vue-cliを使って作成したプロジェクトには含まれているので、個別のインストールは不要です。

次のコマンドを実行してnpmからインストールします。

npm install --save-dev @vue/test-utils jest babel-jest vue-jest

テストを実行しやすいように、package.jsonscriptstestを追加します。

package.json

{
  "scripts": {
    "test": "jest"
  }
}

jest.config.jsの作成と設定

Jestで.vueファイルをテストするためには、jest.config.jsで設定を行う必要があります。プロジェクトルートにjest.config.jsを作成し、次の内容を記述します。

jest.config.js

module.exports = {
  verbose: true,
  moduleFileExtensions: [
    "js",
    "json",
    "vue",
  ],
  transform: {
    "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
    ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
  }
}

【ワンポイント】package.jsonでも設定可能

jest.config.jsを作らずに、package.jsonで設定を記述することもできます。記述する内容は解説にあるものと同じ形式で、jestプロパティに記述します。

package.json

{
  ...
  "jest": {
    ...
    "transform": {
      "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
      ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
    },
    ...
  },
  ...
}

Babelの設定

JestのテストでES Modulesの構文(importなど)を解釈できるよう、Jest用にBabelの設定を記述する必要があります。設定はプロジェクトに合わせて、.babelrcまたはpackage.jsonで行います。

次の設定は.babelrcへの記述例です。env.testの下にテストで使う設定を記述しています。

.babelrc

{
  "presets": [
    ["env", { "modules": false }]
  ],
  "env": {
    "test": {
      "presets": [
        ["env", { "targets": { "node": "current" }}]
      ]
    }
  }
}

package.jsonに記述する場合は、babelプロパティの下に記述します。

これでテストの実行環境が整いました。

【ワンポイント】テストを書く練習をするなら

もしあなたがコンポーネントのテストを書く練習をするために環境構築をするなら、vue-cliでvuejs-templates/webpack-simpleテンプレートを利用することをオススメします。文字どおりシンプルな構成になっていますので、このシリーズの内容を最初からなぞるには最適です。

テストを実行してみる

先述したテストの例にあるコンポーネントとテストファイルを、それぞれMyComponent.vueMyComponent.test.jsとして作成し、テストを実行してみましょう。

MyComponent.vue

<template>
  <div>
    {{text}}
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  props: {
    text: String,
  },
}
</script>

MyComponent.test.js

import {shallow} from '@vue/test-utils'
import MyComponent from './MyComponent.vue'
describe('MyComponent.vue', () => {
  let wrapper
  beforeEach(() => {
    wrapper = shallow(MyComponent)
  })

  describe('props', () => {
    test('propsが受け取れること', () => {
      wrapper.setProps({
        text: 'hello test',
      })
      expect(wrapper.props().text).toBe('hello test')
    })
  })

  describe('template', () => {
    test('textがレンダリングされること', () => {
      wrapper.setProps({
        text: 'hello test',
      })
      expect(wrapper.text()).toBe('hello test')
    })
  })
})

wrapperはvue-test-utilsのshallowによって作成されたVueインスタンスのラッパーオブジェクトです。このオブジェクトには、このテストで使われている.setProps().text()といった、テストを助けるメソッドが用意されています。これらのメソッドについては、次回以降に詳しく解説していきます。

npm testでテストを実行すると、次のような結果が表示されます。

> jest

 PASS  ./MyComponent.test.js
  MyComponent.vue
    props
      ✓ propsが受け取れること (12ms)
    template
      ✓ textがレンダリングされること (1ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.833s
Ran all test suites.

これでVueコンポーネントのテストの第一歩が踏み出せました。

おわりに

今回はテスト実行環境の構築と、vue-test-utilsとJestを使った単純なVueコンポーネントのテストについて解説しました。次回はもう少し複雑なコンポーネントのテストについて、vue-test-utilsの機能を紹介しながら解説します。