参考にさせて頂いたページ
テストを実行する環境の構築
- GitHub - vuejs/vue-test-utils-jest-example: Example project using Jest + vue-test-utils together
- GitHub - babel/babel-bridge: A placeholder package that bridges babel-core to @babel/core.
specファイルの書き方
はじめに
Windowsでもできます。
これから何回かに分けてnpm initするところから、以下のようなことをできる環境を構築していきます。
- webpack4 + babel7 を使ってビルド
- vue-test-utils + jest を使ってテスト実行
- eslintを使って .vue と .js の構文チェック
今日の環境
- Windows10 Home
- node v8.11.1
- npm 5.8.0
前提
以下の記事の手順で基本的なビルド環境の構築をしたところまでが前提です。
- Vuexを使用する基本的なビルド環境を構築する | webpack4.x+babel7+vue.js 2.x 環境構築 2019年3月版 ステップ0001 - Motomichi Works Blog
続きとしてテストを実行できるようにしていきます。
node_modulesを追加する
以下の5つのモジュールを追加する必要があるようです。
Additional Dependencies
vue-test-utils jest babel-jest (for ES2015+ features in tests) vue-jest (for handling *.vue files in tests) jest-serializer-vue (for snapshot tests)
以下のコマンドでインストールしました。
npm install --save-dev @vue/test-utils jest babel-jest vue-jest jest-serializer-vue
package.jsonを編集
package.jsonのscriptsのtestを編集してjestを実行するようにします。
"scripts": { "watch": "webpack -d --watch", "test": "jest" },
jest.config.jsの作成
windowsの場合
copy nul jest.config.js
macの場合
touch jest.config.js
jest.config.jsの編集
以下のように記述します。
module.exports = { // テスト対象の拡張子 "moduleFileExtensions": [ "js", "vue", ], // specファイル中の"^@/(.*)$"にマッチする文字列を"<rootDir>/src/$1"のパスに置き換えてテストを実行 "moduleNameMapper": { "^@/(.*)$": "<rootDir>/src/$1", }, // transformerを設定 "transform": { "^.+\\.js$": "<rootDir>/node_modules/babel-jest", ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest", }, "snapshotSerializers": [ "<rootDir>/node_modules/jest-serializer-vue", ], }
ここまでやった段階でのpackage.json
以下のようになっています。
{ "name": "webpack_4_vue_introduction", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "watch": "webpack -d --watch", "test": "jest" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@babel/cli": "^7.2.3", "@babel/core": "^7.4.0", "@babel/preset-env": "^7.4.2", "@vue/test-utils": "^1.0.0-beta.29", "babel-jest": "^24.5.0", "babel-loader": "^8.0.5", "jest": "^24.5.0", "jest-serializer-vue": "^2.0.2", "vue-jest": "^3.0.4", "vue-loader": "^15.7.0", "vue-template-compiler": "^2.6.10", "webpack": "^4.29.6", "webpack-cli": "^3.3.0" }, "dependencies": { "vue": "^2.6.10", "vuex": "^3.1.0" } }
testディレクトリを作成する
mkdir test
空ファイルを二つ作成する
windowsの場合
以下のコマンドで作成できると思います。
copy nul test\TextFieldUnit.spec.js copy nul test\TextField.spec.js
macの場合
以下のコマンドで作成できると思います。
touch test/TextFieldUnit.spec.js touch test/TextField.spec.js
./test/TextFieldUnit.spec.jsの作成とその記述内容
import { shallowMount, createLocalVue } from '@vue/test-utils' import Vuex from 'vuex' // modules import textFieldUnit from '@/javascripts/vue_applications/common/modules/textFieldUnit.js' // components import TextFieldUnit from '@/javascripts/vue_applications/common/components/TextFieldUnit.vue' const localVue = createLocalVue() localVue.use(Vuex) describe('TextFieldUnit.vue', () => { let store; beforeEach(() => { // 本来のthis.$storeに入るものと同様のオブジェクト構造を作成します。 store = new Vuex.Store({ state: {}, getters: {}, mutations: {}, actions: {}, modules: { textFieldUnit, }, }) }) it('mutationsの動作確認', () => { const state = store.state.textFieldUnit; const key = 'count'; textFieldUnit.mutations.setState(state, { key, value: state[key] + 1, }); expect(state[key]).toBe(1); }); it('ボタンのclickイベントが発火したとき', () => { const wrapper = shallowMount(TextFieldUnit, { store, localVue }) const button = wrapper.find('button') // 初期値の検証 expect(button.text()).toBe('count: 0') // イベント発火 button.trigger('click') // 変更後の値の検証 expect(button.text()).toBe('count: 1') }); })
./test/TextField.spec.jsの作成とその記述内容
import { shallowMount, createLocalVue } from '@vue/test-utils' import Vuex from 'vuex' // modules import textFieldUnit from '@/javascripts/vue_applications/common/modules/textFieldUnit.js' import textField from '@/javascripts/vue_applications/common/modules/textField.js' // components import TextField from '@/javascripts/vue_applications/common/components/TextField.vue' const localVue = createLocalVue() localVue.use(Vuex) describe('TextField.vue', () => { let store; beforeEach(() => { // 本来のthis.$storeに入るものと同様のオブジェクト構造を作成します。 store = new Vuex.Store({ state: {}, getters: {}, mutations: {}, actions: {}, modules: { textFieldUnit, }, }); }); it('mutationsの動作確認', () => { const state = store.state.textFieldUnit.textField; const key = 'value'; textFieldUnit.mutations.setState(state, { key, value: 'editedValue', }); expect(state[key]).toBe('editedValue'); }); it('テキストフィールドのinputがイベント発火したとき', () => { const wrapper = shallowMount(TextField, { store, localVue }); const input = wrapper.find('input'); const syncedText = wrapper.find('.test-synced-text'); // 初期値の検証 expect(input.element.value).toBe('defaultValue'); expect(syncedText.text()).toBe('value: defaultValue'); // イベント発火 input.element.value = 'editedValue'; input.trigger('input'); // 変更後の値の検証 expect(input.element.value).toBe('editedValue'); expect(syncedText.text()).toBe('value: editedValue'); }); });
testを実行してみる
package.jsonのscriptsに定義してあるので、以下のコマンドで実行できます。
npm run test
scoped packagesになったバージョンの@babel/babel-core
を使っているため以下のようなメッセージが出てテスト実行に失敗します。
● Test suite failed to run Cannot find module 'babel-core' at Object.<anonymous> (node_modules/vue-jest/lib/compilers/babel-compiler.js:1:15)
babel-bridge(@babel/coreへの橋渡し)
GitHub - babel/babel-bridge: A placeholder package that bridges babel-core to @babel/core.
さきほどのエラーでは Cannot find module 'babel-core'
でした。
'babel-core' を探しにいったときに '@babel/core' へ橋渡しをできるようにします。
npm install --save-dev babel-core@^7.0.0-bridge.0 @babel/core
もう一度testを実行してみる
もう一度testを実行してみます。
npm run test
以下のように4つ成功したかと思います。
Test Suites: 2 passed, 2 total Tests: 4 passed, 4 total
ここまでやった段階のpackage.jsonの記述内容
{ "name": "webpack_4_vue_introduction", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "watch": "webpack -d --watch", "test": "jest" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@babel/cli": "^7.2.3", "@babel/core": "^7.4.0", "@babel/preset-env": "^7.4.2", "@vue/test-utils": "^1.0.0-beta.29", "babel-core": "^7.0.0-bridge.0", "babel-jest": "^24.5.0", "babel-loader": "^8.0.5", "jest": "^24.5.0", "jest-serializer-vue": "^2.0.2", "vue-jest": "^3.0.4", "vue-loader": "^15.7.0", "vue-template-compiler": "^2.6.10", "webpack": "^4.29.6", "webpack-cli": "^3.3.0" }, "dependencies": { "vue": "^2.6.10", "vuex": "^3.1.0" } }
おまけ
以下のような感じでvmのcomputedやmethodsにもアクセスできます。
wrapper.vm.hoge
おわりに
testディレクトリに入っている.spec.jsファイルはもっとディレクトリ階層を深くしてもテストを実行できます。
以下のようなテストが実行できるようになりました。
- Vueコンポーネントのテスト
- Vuexのstoreのテスト
- Vueとは関係なく定義した関数のテスト
今日はここまで。
次回は.vueの中にstyleを書けるようにしていこうと思います。