Vuetify + VeeValidate + Cypress で E2E テストを試す

Vuetify + VeeValidate の構成に Cypress を使った E2E テストを組み込んでみました。
2020.09.29

vue-cli のプラグインに @vue/cli-plugin-e2e-cypress が用意されていますので、 それを使って以前の構成に Cypress による E2E テストを追加してみました。

cli-plugin-e2e-cypress を組み込む

以下を実行するだけです。

% vue add e2e-cypress
% npm update

なお、Cypress 最新は v5 ですが、このプラグインで追加されるものは v4 となっています。 issue も上がっていますが、未対応のようです。

E2Eテストの実行

Vuetify ダイアログが表示されることを確認するテスト

tests/e2e/specs/test.js が追加されるので、とりあえずボタンを押してダイアログが表示されることを確認するだけのテストに修正してみます。

describe('My First Test', () => {
  it('ダイアログが表示されること', () => {
    cy.visit('/')
    cy.contains('div', 'VeeValidate')
    cy.contains('button', 'Vuetifyダイアログ').click()
    cy.contains('div.v-dialog', 'Select Country').should('be.visible')
  })
})

修正したらテストを実行します。

package.jsonscriptstest:e2e が追加されるので、以下のように実行出来るようになります。

% npm run test:e2e

実行すると以下のようなウィンドウが表示されます。

E2Eテスト起動直後のウィンドウ

テストファイル(test.js)をクリックすると、Chromeが立ち上がってテストを実行してくれます。

E2Eテスト結果

テストの実行結果とスクリーンショットがその場で確認出来るので、大変便利です。 以前(例えば Rails + Capybara とか)はスクリーンショットを残すところを含めた仕組み作りが面倒だったので、楽すぎて感動しました。

また、テストに失敗した場合は、以下のように具体的な情報を出力してくれます(ハイライト行が失敗する箇所)。

describe('My First Test', () => {
  it('ダイアログが表示されること', () => {
    cy.visit('/')
    cy.contains('div', 'VeeValidate')
    cy.contains('button', 'Vuetifyダイアログ').click()
    cy.contains('div.v-dialog', 'Select Language').should('be.visible')
  })
})

E2Eテスト結果(失敗)

VeeValidate のバリデーションが効いていることを確認するテスト

続いて、バリデーションが動作しているかどうか確認してみます。

以前実装したダイアログは、国名を選択しないと SAVE が有効にならないようにしていました。

以前実装したダイアログ

これを確認したい場合はこんな感じで書けます。

  it('ダイアログの Belgium 項目を選択できること', () => {
    cy.visit('/')
    cy.contains('div', 'VeeValidate')
    cy.contains('button', '+VeeValidateダイアログ(対策済)').click()
    cy.contains('div.v-dialog', 'Select Country').should('be.visible')
    cy.contains('button', 'Save').should('be.disabled')
    cy.contains('div', 'Belgium').click()
    cy.contains('button', 'Save').should('be.enabled')
    cy.contains('button', 'Save').click()
  })

なお、 test.js を修正して保存するだけで、自動的にテストが再実行されます。

バリデーション確認E2Eテスト

ダイアログが表示されているか、未選択の場合は SAVE が無効になっていることなどもチェックしています。 実際にここまでチェックするかどうかは要件次第ではありますが、期待した動作をしているようです。

以前別のE2Eテストを実装していた際には、バリデーションが非同期で動く関係で、待ち合わせを入れていく必要があった場合もあったのですが、 今の所は素直に書けています。

ただ、今後 API の結果を待ち合わせる際や、複雑な UI を伴う場合など非同期を強く意識するケースが出てくると思いますので、その際に対応したことは別途報告できればと思います。

VeeValidate のエラーメッセージを確認するテスト

最後に、バリデーションに引っかかった際にメッセージが表示されるかどうか確認してみます。 メッセージ変更や多言語化の影響を受けにくくするよう、ここでは何らかのメッセージが出ていることだけを確認します。

  it('AWSアカウントIDのフォーマット違反でメッセージが表示されること', () => {
    cy.visit('/')
    cy.get('div#form-vee-validate').within(() => {
      cy.contains('label', 'AWSアカウントID').next('input').type('hoge')
      cy.get('.v-messages__message').should('not.be.empty')
    })
  })

エラーメッセージ確認E2Eテスト

<v-text-field><input>を特定する方法は少し工夫が必要でした。 以下のページが参考になりました。

なお、メッセージのテストに関する指針などは、この部分を参考にすると良いと思います(特にVeeValidate固有の話ではない)。

また、エラーメッセージの要素を特定するためにVuetifyの内部クラス(.v-messages__message)を使っているのが微妙に感じるので、別途クラスを振った方がいいかもしれません (Vuetifyの仕様でそうそう変わるところでは無い予感はあるが…)。

最後に

上記 Qiita のページにもリンクがあった Cypress のベストプラクティスのページと、VeeValidate のテストに関する考慮事項のページは目を通しておいたほうが良さそうです。

また、他にも興味深い機能が備わっているので、色々触ってみたいと思います。

例によって、上記確認出来るソースを以下リポジトリに置いています。