masakiのブログ Written by masaki shibayama

【2023年最新版】Vue.jsとJestでの単体テストのコードの書き方を解説

Programming WebApp

こんにちは。masakiです。
今回は、Vue.jsとJestで単体テストを書く方法について解説します。
今回は、Vue.jsの勉強をしてコードを書くことはできるようになったけど、単体テストのコードをどうやって書いていったら良いかがわからないという方を対象読者にしています。

単体テストをする意義

まず、単体テストのコードの書き方を解説する前に、そもそもなぜテストコードを書かないといけないのかについて触れておきたいと思います。
結論から言うと、テストコードを書く理由は、本番環境のコードのリグレッション(新規で機能を追加した時に、今まで動いていた箇所が動かなくなること)を防ぐためです。

つまり、テストとは要するにソフトウェアの変更を確実に行なっていくための技術なのです。

ここで、テストコードが全くない場合のことをイメージしてもらうと良いのですが、このようなケースでは新規で機能を追加するたびに別の箇所でバグが発生するといった、目も当てられないような状況に陥ります。こうなってしまうと、少し機能を追加するだけでも大変になってしまい、開発の生産性がはるかに落ちてしまいます。

使用するライブラリ

前置きはさておき、それでは早速Vue.jsでの単体テストの書き方について解説していきます。
Vue.jsで単体テストを書くには、大きく分けて2つのライブラリを用いるのが一般的です。

  • Jest(もしくはvitest)
  • vue-test-utils

Jest

JestはJavaScriptのテスト用ライブラリです。(TypeScriptももちろんサポートしています。)
基本的には、マッチャーと呼ばれる関数を使って、実際の値と予測値が同じかどうかを判定することでテストをしていきます
最近ではVietestというライブラリも出てきていますが、基本的な書き方はあまりJestと変わりません。
なので、今回はJestを使って単体テストの解説をしていきます。

vue-test-utils

Jest以外には、vue-test-utilsというライブラリを用います。
これは何のために用いるかというと、テストしたいコンポーネントのインスタンスを取得するためです。
このインスタンスを取得することで、インスタンス内のリアクティブな変数(つまり、コンポーネント内で使われるリアクティブな変数)を扱うことができます。

つまり、テストするコンポーネントで扱っているデータを取ってくるのがvue-test-utilsの役割です

単体テストの流れ

単体テストの流れは以下のとおりです。

  1. テストしたいコンポーネントをマウントによって取得する
  2. テストしたい値を取得
  3. 実際の値と予測値がマッチしているかどうかを判定する

サンプルコード

例えば、以下のようなForm.vueがあるとします。

このForm.vueに対して、
Form.test.jsというテストファイルを書いていきます。


import { shallowMount } from "@vue/test-utils";
import Form from "@/components/Form.vue";

describe("test", () => {
  it("username test", () => {
    const wrapper = shallowMount(Form);

    const usernameElement = wrapper.get(".username");
    expect(usernameElement.element.value).toBe("");
  });

  it("password test", () => {
    const wrapper = shallowMount(Form);

    const passwordElement = wrapper.get(".password");
    expect(passwordElement.element.value).toBe("");
  });
}));

上記のコードについて説明します。

まずdescribe()メソッドは、1つ1つのテストケースをまとめるためのメソッドです。今回の例では、it()メソッドの中身が個々のテストケースです。
it()では、入力フォーム中のユーザー名およびパスワードの値が空文字であるかどうかを判定しています。
vue-test-utilsには大きく分けてshallowMount()とmount()という2つのメソッドがありますが、ここでは子コンポーネントをスタブ化するshallowMount()の方を用いています。このメソッドで取得したコンポーネントのインスタンスを、wrapperという変数に格納しています。

wrapper.get(クラス名)

とすると、そのクラス名に該当するタグの情報を、コンポーネントから取得することができます。
wrapperは様々なプロパティを持つので、これらのプロパティを用いて欲しい値を取得し、予測値(ここでは空文字)と一致するかどうかを、マッチャーであるtoBe()を用いて判定しているといった具合です。

今回はさらっと解説しましたが、wrapperのプロパティやマッチャーにはこの他にもかなりたくさんの関数があります。
この辺りは必要になった時にドキュメントを見ながら使っていけば問題ないと思います。

ちなみに、単体テストをするときのコツとしては、常にコンポーネントの内部ではなく出力結果に着目することです。このようなブラックボックステストが、単体テストのテストケースを作成する上では有効な方法です。

以上、最後まで読んでいただきありがとうございました。

参考書籍

Vue 3 フロントエンド開発の教科書

これからはじめるVue.js 3実践入門

単体テストの考え方/使い方

【Vue3】Jest & Vue Test Utils 詳解 チュートリアル
https://zenn.dev/tentel/books/08b63492b00f0a

はじめてのJest入門
https://zenn.dev/ganezasan/books/78676684ccdeb090f7b8