Nuxt.jsでユニットテスト(Karma+Jasmin)。

Nuxt.jsでユニットテスト(Karma+Jasmin)

皆さん、Nuxt.jsを使っていますか?

Nuxt.jsは、Vue.jsでUniversalな開発ができるフレームワークです。
Reactにも同様にNext.jsがありますが、Next.jsの思想から作られたのがNuxt.jsになります。
先日正式版がリリースされたので、これまでアルファバージョンだからと二の足を踏んでいた人の利用も増えてくることでしょう。

Nuxt.jsを使用すればVueで作成したアプリケーションで、サーバサイドレンダリングを簡単に構築することができます。
他にも色々とメリットがありますが、Vue.jsだけを使うよりもやや複雑になっていまうのがデメリットでしょうか。

公式サイトにユニットサイトのガイドがない!

デメリットという程でもありませんが、Nuxt.jsを使った場合にユニットテストの方法がなかなか見つからず苦労しました。
公式サイトにテストの記述があるのですが、エンドツーエンドの記載しかありません。
https://ja.nuxtjs.org/guide/development-tools

というわけで、今回はNuxt.jsでユニットテストを行います。
テストツールはVue.jsの公式サイトでも紹介されている、Karmaを使用したいと思います。
https://jp.vuejs.org/v2/guide/unit-testing.html

関係ないですが、VueもNuxtも日本語マニュアルが用意されていて、とても助かりました。

まずはKarmaをインストール

Nuxt.jsをインストールした状態から始めます。
下記のような画面になっているかと思います。

Nuxt.jsをインストール

ではKarmaと関連ファイルをインストールします。

npm install karma --save-dev
npm install karma-jasmine jasmine-core karma-phantomjs-launcher karma-chrome-launcher --save-dev

Vue.jsにwebpackを使うと良いよとあるので、こちらもインストールします。

npm install webpack karma-webpack --save-dev

インストールが完了したら、Karmaの設定ファイルを作成しましょう。
今回webpackを使用するので、下記のような設定になります。

/test/unit/karma.conf.js

var webpackConfig = require('./webpack.config.js')
delete webpackConfig.entry


module.exports = function (config) {
  config.set({
    browsers: ['Chrome'],
    frameworks: ['jasmine'],
    files: ['index.js'],
    preprocessors: {
      'index.js': ['webpack']
    },
    webpack: webpackConfig,
    webpackMiddleware: {
      noInfo: true
    },
    singleRun: true
  })
}

/test/unit/webpack.config.js

const resolve = require('path').resolve;
const root = resolve('.')


module.exports = {
  resolve: {
    modules: [root + '/node_modules'],
    extensions: ['.js', '.vue'],
    alias: {
      '~': root,
      'static': root + '/static',
      '~static': root + '/static',
      'assets': root + '/assets',
      '~assets': root + '/assets',
      '~plugins': root + '/plugins',
      '~store': root + '/.nuxt/store',
      '~router': root + '/.nuxt/router',
      '~pages': root + '/pages',
      '~components': root + '/components',
      '~lib': root + '/lib',
    }
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
        test: /\.vue$/,
        exclude: /node_modules/,
        loader: 'vue-loader',
      }
    ]
  }
};

/test/unit/index.js

var testsContext = require.context('.', true, /\.spec$/)
testsContext.keys().forEach(testsContext)

テストをしてみる

まずViewを下記のように公式サイトの例と同じ内容にしてみます。

/pages/index.vue

<template>
  {{ message }}
</template>


<script>
  export default {
    data () {
      return {
        message: 'hello!'
      }
    },
    created () {
      this.message = 'bye!'
    }
  }
</script>

そしてテストファイルも作成します。

/test/unit/index.spec.js

// Vue と テスト対象のコンポーネントをインポートする
import Vue from 'vue'
import MyComponent from 'path/to/MyComponent.vue'

// テストランナーや検証には、どのようなライブラリを用いても構いませんが
// ここでは Jasmine 2.0 を用いたテスト記述を行っています。
describe('MyComponent', () => {
  // コンポーネントの options を直接検証します。
  it('has a created hook', () => {
    expect(typeof MyComponent.created).toBe('function')
  })

  // コンポーネントの options 内にある関数を実行し、
  // 結果を検証します。
  it('sets the correct default data', () => {
    expect(typeof MyComponent.data).toBe('function')
    const defaultData = MyComponent.data()
    expect(defaultData.message).toBe('hello!')
  })

  // コンポーネントインスタンスをマウントして検証します。
  it('correctly sets the message when created', () => {
    const vm = new Vue(MyComponent).$mount()
    expect(vm.message).toBe('bye!')
  })

  // マウントされたコンポーネントインスタンスを描画して検証します。
  it('renders the correct message', () => {
    const Constructor = Vue.extend(MyComponent)
    const vm = new Constructor().$mount()
    expect(vm.$el.textContent).toBe('bye!')
  })
})

さあ、これで準備が出来ました。
テストを実行してみましょう。

karma start test/unit/karma.conf.js

「Executed 4 of 4 SUCCESS」が出ればテスト成功です。
お疲れ様でした。

最後に

いかがでしたでしょうか。
Nuxt.jsを使ってみて、私の勉強不足で躓いてしまうことも多々ありますが、サーバサイドレンダリングが簡単にできてしまうところは大きなメリットかと思います。

Vue.jsやNuxt.jsを使用したお仕事、お待ちしております!