🧪

最低限使えるJestの使い方

2022/12/30に公開約3,000字

JavaScriptのテストフレームワーク、Jestの「これさえ覚えておけば、とりあえず最低限の使いかたができる」という使いかたです。

とりあえずセットアップする

テストしたいJavaScriptプロジェクトのルートフォルダで、以下のコマンドを実行します。

npm install --save-dev jest

npmが入ってないかたはWindowsの場合はwinget install OpenJS.NodeJSでインストールしておいてください。

さっそく使う

ルートフォルダ配下にある*.test.jsというファイルを対象にテストを行ってくれます。Visual Studio Codeの場合、vscode-jestという拡張を入れれば。関数の定義の左からボタンで実行したり、テストエクスプローラー上から直接実行することもできます。
https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest

そのまえに今回テスト対象となるソースコード

あらかじめこのようなファイルがmain.jsという名前でルートフォルダに配置されているものとします。

main.js
function sum(a,b) {
  return a+b;
}

async function throwError(){
  throw new Error("test");
}

module.exports = {
  sum,
  throwError
}

とりあえずテストする

テストコードはtest()という関数で定義します。第一引数はテストの名称、第二引数に実行コードを書きます。

const main = require("./main");
test("sum()関数に二つの整数を指定した場合、その値を合算した値を返却することを確認する", () => {
  expect(main.sum(2, 3)).toBe(5); // main.sum()の実行結果が5であればテスト成功
});

なお、ここでrequireを使う際の参照パスは、テストファイルからの相対パスとなります。例えばよくあるように、srcフォルダにソースファイル、testフォルダにテストファイルが入っている場合。../で上のフォルダを参照する必要があります。

例外が発生することをテストする

例会が発生したことを確認するためのテストとしてtoThrow()がありますが、これがまたちょっと厄介。
非同期実行の関数と同期実行の関数で呼び出し方が変わります。とりあえず非同期実行の場合のみ。

test("throwError()関数を実行すると例外か発生することを確認する。", () => {
  expect(main.throwError()).rejects.toThrow(); // 例外が発生したらテスト成功
});

なお、ここではawait文を使ってはいけません。なので・・・

test("throwError()関数を実行すると例外か発生することを確認する。", async() => {
  // --------------------------------------------------------------^ いらない
  expect(await main.throwError()).rejects.toThrow();
  // ----^ いらない
});

こういう風に書くと、構文エラーが出ないので一見動くように見えますが、実際には確実にテストが失敗します

タイムアウトを指定する

Jestのテストはデフォルト5000ミリ秒でタイムアウトするようになっています。タイムアウトの時間を過ぎるとどのような状態であっても、テスト失敗とみなされます。

それ以上に時間がかかる処理をテストする場合は、テスト関数の第三引数に時間を設定します。

test("長い時間がかかるテスト", () => {
  // ながーーい処理
}, 8000);

この場合、タイムアウトは5000ミリ秒から8000ミリ秒になります。

全てのテストを実行する

.\node_modules\.bin\jestを実行します。package.jsonを編集してnpm run jestなどとして実行できるようにしておくと良さそう。

その他、Visual Studio Codeであれば。vscode-jestの機能を使ってテストエクスプローラーから実行することもできます。

実行時の注意

実行時の注意として、中でサーバーなどを立ち上げた場合、ちゃんと終了させる必要があります。
終了していない場合、テストがいつまでたっても終了しない扱いになるのか、再度テストを実行することができません。

test("サーバへの通信確認", async() => {
  const express = require('express');
  const aport = await require("aport")();
  const app = express();
  const server = app.listen(aport);
  app.put("/testmethod", (req, res) => {
    if(req.method == "PUT"){
      res.status(200);
      res.end();
    }else{
      res.status(403);
      res.end();
    }
  });
  try {
    /* HTTPサーバにアクセスする処理 */
  } catch (error){
    new Error(error);
  } finally{
    server.close(); // 必須
  }
}

上記必須の行がないと、次のテストが実行できません。

この他にもいくつかのリソースは、しっかり閉じないと次のテストが行えない場合がありますので、次のテストが動かせないというときは、閉じ忘れたリソースがないかどうか確認をしてみてください。

参照記事

Discussion

ログインするとコメントできます