vueのサンプルテストを書いてみる

vueとgoでポートフォリオ作ったんだけど、vueのテストってどうやって書くんだろう・・・ということでちょっと見てみる。

vue-test-utilsを使ってみる

以下のvue公式のサンプルを試してみよう。

vue-test-utils.vuejs.org

vue-test-utils は Vue コンポーネントを隔離してマウントし、必要な入力(プロパティ、注入、そしてユーザイベント)をモックし、そして出力(描画結果、カスタムイベントの発行)を検証することでテストします。

なるほどどうやらモックを作ってそのモックを通してテストするようだ。

マウントされたコンポーネントは Wrapper の内部に返されます。これは、基の Vue コンポーネントインスタンスを操作、トラバース、クエリ処理するための多くの便利なメソッドを公開しています。

Wrapperってやつがコンポーネントをなんかうまくやってくれるらしい。

vue-test-utils.vuejs.org

なんかWrapperっていうのを使うとコンポーネントをラップしてくれるのかな。で、テストではそのラップされたものを使えと。コード見る感じそんな気がする 。

import { mount } from '@vue/test-utils'
import Counter from './counter'

// コンポーネントがマウントされ、ラッパが作成されます。
const wrapper = mount(Counter)

test-utilsのmount関数を使ってコンポーネントをラップ。そしてこのラップされえたwrapperをいじっていくんやな。

import { mount } from '@vue/test-utils'
import Counter from './counter'

describe('Counter', () => {
  // コンポーネントがマウントされ、ラッパが作成されます。
  const wrapper = mount(Counter)
  console.log(wrapper.html())
  // => <div><span class="count">0</span> <button>Increment</button></div>
  
})

mountで作成されたラッパーはラッパーとしての関数を持っているから例えば、.html()なんかすると、そのコンポーネントが持っているhtmlを返してくれる。

記事通りに進めてこんな感じに書くと、テストは通るね。

import { mount } from '@vue/test-utils'
import Counter from './counter'

describe('Counter', () => {
  // コンポーネントがマウントされ、ラッパが作成されます。
  const wrapper = mount(Counter)

  it('renders the correct markup', () => {
    expect(wrapper.html()).toContain('<span class="count">0</span>')
  })

  // 要素の存在を確認することも簡単です
  it('has a button', () => {
    expect(wrapper.contains('button')).toBe(true)
  })
})
$ npm test

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.527s

このexpectとかtoBeなんていうメソッドはJestに備わっているものっぽい。

jestjs.io

テストするときにはこのJestのメソッドとvue-test-utilsのメソッドを組み合わせてやっていく感じか。なんかテストコード見てるとRspec感がなくもない。

jestは拡張子でテストファイル判断。

デフォルトでは、Jest はプロジェクト全体で .spec.js または .test.js 拡張子を持つすべてのファイルを再帰的に取得します。これがあなたのニーズに合わない場合は、package.json ファイルの config セクションでtestRegex を変更することが可能です。

ユーザのインタラクションをシミュレーションする

このサンプルのコードにはボタンをクリックするとdataとして持っている数値をincrementするっていう実装があるんだけど、こんなのもテストできるらしい。

import { mount } from '@vue/test-utils'
import Counter from './counter'

describe('Counter', () => {
  // コンポーネントがマウントされ、ラッパが作成されます。
  const wrapper = mount(Counter)

  it('button click should increment the count', () => {
    expect(wrapper.vm.count).toBe(0)
    const button = wrapper.find('button')
    button.trigger('click')
    expect(wrapper.vm.count).toBe(1)
  })
})

wrapper.vm.countでvueインスタンスのdataであるcountにアクセスしてるのね。インクリメントするために、ボタンのラッパである .trigger() を呼び出すことでクリックしている。