Webpacker を使っている Rails アプリに Vue のユニットテストを導入する

真っ白な環境に Vue のユニットテストを導入する記事を以前書いた。

numb86-tech.hatenablog.com

今回は、Webpacker を用いて Vue を使用している Rails アプリに、Vue のユニットテストを導入する方法を書いていく。
rails newでプロジェクトを作成するところからやっていく。

前述の記事と同様、テストフレームワークJestアサーションライブラリにはpower-assertを使う。

以下のバージョンで動作確認した。

npmパッケージのバージョンは以下。

  • @rails/webpacker@3.5.5
  • @vue/test-utils@1.0.0-beta.26
  • babel-jest@23.6.0
  • babel-preset-power-assert@2.0.0
  • jest@23.6.0
  • power-assert@1.6.1
  • vue-jest@3.0.1

まずはプロジェクトを作り、そこに移動する。

$ rails new PROJECT_NAME --webpack
$ cd PROJECT_NAME

Vueの利用を開始。

$ bundle exec rails webpacker:install:vue

こうすると Vue を使えるようになるだけでなく、app/javascript/app.vueというサンプルコンポーネントも作られる。
今回はこのコンポーネントを対象にテストを書く。

まずはユニットテストに必要なライブラリをインストール。

$ yarn add -D jest babel-jest vue-jest @vue/test-utils

package.jsonに、Jest の設定を追加する。

diff --git a/package.json b/package.json
index 2bd7463..90196a1 100644
--- a/package.json
+++ b/package.json
@@ -13,5 +13,14 @@
     "jest": "^23.6.0",
     "vue-jest": "^3.0.1",
     "webpack-dev-server": "2.11.2"
+  },
+  "jest": {
+    "roots": [
+      "app/javascript"
+    ],
+    "transform": {
+      "^.+\\.js$": "babel-jest",
+      "^.+\\.vue$": "vue-jest"
+    }
   }
 }

rootsで、対象とするテストファイルの場所を指定している。
app/javascriptと指定したので、このディレクトリ以下の、ファイル名の末尾が.test.js.spec.jsになっているファイル、そして__tests__ディレクトリに入っているファイルが、対象になる。

transformでは、テストが可能な形にトランスパイルする設定を記述している。先程インストールしたbabel-jestvue-jestはここで使う。

JSファイルを Babel でトランスパイルするように設定しているので、Babel の設定も書く必要がある。
プロジェクト開始時に既に.babelrcは作られているので、そこにテスト用の設定を追加する。

diff --git a/.babelrc b/.babelrc
index ded31c0..0428c4b 100644
--- a/.babelrc
+++ b/.babelrc
@@ -14,5 +14,11 @@
     "syntax-dynamic-import",
     "transform-object-rest-spread",
     ["transform-class-properties", { "spec": true }]
-  ]
+  ],
+
+  "env": {
+    "test": {
+      "presets": ["env"]
+    }
+  }
 }

次に、package.jsonを編集して、$ yarn testでテストが実行されるようにした。

diff --git a/package.json b/package.json
index 90196a1..e1cb36e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,9 @@
 {
   "name": "jest-blog",
   "private": true,
+  "scripts": {
+    "test": "jest"
+  },
   "dependencies": {
     "@rails/webpacker": "3.5",
     "vue": "^2.5.17",

あとはapp/javascript以下にテストファイルを書けばいい。

app/javascript/__tests__/app.test.jsを書いてみた。
Jest などと一緒に最初にインストールした@vue/test-utilsは、Vue のユニットテストを書くための公式ライブラリ。

import {shallowMount} from '@vue/test-utils';

import App from '../app.vue';

const assert = require('assert');

describe('Assert', () => {
  describe('Vue', () => {
    it('shallowMount', () => {
      const wrapper = shallowMount(App);
      assert.equal(wrapper.text(), 'Hello Vue!');
    });
  });
});

これで$ yarn testを実行すれば、テストが実行される。

既にテストを書いていける状態になったが、power-assertを入れてテストを書きやすくする。

必要なライブラリをインストール。

$ yarn add -D power-assert babel-preset-power-assert

トランスパイルが必要なので、.babelrcenv.testに設定を追加する。

diff --git a/.babelrc b/.babelrc
index 0428c4b..47cfe92 100644
--- a/.babelrc
+++ b/.babelrc
@@ -18,7 +18,7 @@
 
   "env": {
     "test": {
-      "presets": ["env"]
+      "presets": ["env", "power-assert"]
     }
   }
 }

しかしこれで$ yarn testを実行したらエラーになった。

Requires Babel "^7.0.0-0", but was loaded with "6.26.3".

これを書いている時点でのbabel-preset-power-assertの最新バージョンは3.0.0
そしてこのバージョンは Babel のv7で使える。
だが、Rails5.2の Webpacker 環境で使われている Babel は、デフォルトではv6らしい。

そのため2.xbabel-preset-power-assertを使う必要がある。

Babel7 is incompatible with Babel6.
For Babel6, you need to use the 2.x release of babel-preset-power-assert.

https://github.com/power-assert-js/babel-preset-power-assert

バージョンを指定して改めてインストールする。

$ yarn add -D babel-preset-power-assert@2.0.0

これで、正しく動くようになった。

わざとテストを失敗させてみる。

      assert.equal(wrapper.text(), 'Hello Vue')
                   |       |                   
                   |       "Hello Vue!"        
                   VueWrapper{isFunctionalComponent:undefined,_emitted:#Object#,_emittedByOrder:#Array#}

詳細な情報が表示され、テストを効率的に書けるようになった。