LoginSignup
16
12

More than 5 years have passed since last update.

nuxt.js の Unit Test のツラミについて

Last updated at Posted at 2017-12-08

これ、みんなどうやっているのか聞きたいので投稿してみる。
もっといい方法が存在するのであれば教えてください。


nuxt.js は SSR によるアプリケーション開発における必要なものが大体揃っており、良いなーということで使い始めてはいるのですが、やはり、まだまだRC版ということで課題もあります。今回は Unit テストで詰まりました。

nuxt.js では、nuxt-build により store をまとめたり、nuxt.js がプリセットで用意している component を .nuxt/ ディレクトリに用用意する。さらに面倒なことに、.nuxt で展開されているものは、webpackで使う前提となっています。 内部的には、 require.context を利用しているためです。

nuxt.js 公式では、 ava による e2e テストの方法について公式で述べているものの、Unitテストについてはイマイチ情報が少ないです。 Unit testing Issue #461 nuxt/nuxt.js あたりも参照のこと。

// 上記の e2e のテストについても毎回 build が走ってしまうので、個人的には気に食わない。

ということで、自分なりにテスト方法について模索してみました。

前提

ここでは、vue-init webpack によりデフォルトでオススメされる、jest をテストツールとして使います。

導入

yarn で必要なものを入れていく

yarn add -D babel-core babel-jest babel-plugin-dynamic-import-node \
           babel-plugin-transform-es2015-modules-commonjs \
           babel-plugin-transform-runtime babel-preset-env \
           babel-preset-stage-2 babel-register jest jest-serializer-vue vue-jest

必要なファイルを変更したり、作っていく作業を行う

.babelrc
{
  "presets": [
    ["env", {
      "modules": false
    }],
    "stage-2"
  ],
  "plugins": ["transform-runtime"],
  "env": {
    "test": {
      "presets": ["env", "stage-2"],
      "plugins": ["transform-es2015-modules-commonjs", "dynamic-import-node"]
    }
  }
}
.eslintrc.js
module.exports = {
  env: {
    jest: true // jest を true にする
  }
}
test/unit/jest.conf.js
const path = require('path')

module.exports = {
  rootDir: path.resolve(__dirname, '../../'),
  moduleFileExtensions: [
    'js',
    'json',
    'vue'
  ],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/$1'
  },
  transform: {
    '^.+\\.js$': '<rootDir>/node_modules/babel-jest',
    '.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
  },
  snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
  setupFiles: ['<rootDir>/test/unit/setup'],
  mapCoverage: true,
  coverageDirectory: '<rootDir>/test/unit/coverage',
  collectCoverageFrom: [
    'components/**/*.{js,vue}'
  ]
}
test/unit/setup.js
import Vue from 'vue'
Vue.config.productionTip = false

テスト記述

test/unit/specs/components/AppHeader.spec.js
import Vue from 'vue'
import Vuex from 'vuex'
import VueRouter from 'vue-router'
import VueI18n from 'vue-i18n'
import AppHeader from '@/components/AppHeader.vue'

const store = require('@/store/')

Vue.use(VueRouter)
Vue.use(Vuex)
Vue.use(VueI18n)

describe('AppHeader.vue', () => {
  it('pass', () => {
    AppHeader.components = {}

    // nuxt-link component を使っている場合は、モックを載せる
    // この中身は、.nuxt/components/nuxt-link.js にも出来ているので、
    // ビルドが行われている前提であれば、そちらを呼んでも良い。
    AppHeader.components.NuxtLink = {
      name: 'nuxt-link',
      functional: true,
      render (h, {data, children}) {
        return h('router-link', data, children)
      }
    }

    const Constructor = Vue.extend(AppHeader)

    // VueI18n を使っているので、載せる。
    // 但しUnitレベルでは別にデータは不要なので、silentTranslationWarn: true にして警告を消す
    const vm = new Constructor({router: new VueRouter(), i18n: new VueI18n({silentTranslationWarn: true})})

    // store/index.js (Module Mode) から store を作る作業
    vm.$store = new Vuex.Store(Object.assign(store, {
      state: store.state()
    }))
    vm.$mount()

    // テストを記述する
  })
})

テスト実行

yarn run から実行できるようにする

package.json
{
  "scripts": {
    "unit": "jest --config test/unit/jest.conf.js "
  }
}
yarn run unit

悩ましいポイント

  • 今のところ、ビルド済みの .vue/ に依存しない形で書いているが、依存させたほうが良いかな?
  • Vuex モジュールが増えてくると面倒なことになりそう。
  • *.vue ファイルのカバレッジが、何故かちゃんと取得できない場合もある。
16
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
12