[緑野仙踪のプロデューサーNINJA]TDD(3)


JestによるSnapshotテスト


snapshot testing


スナップショットテスト(snapshot testing)は、ある機能の予想結果を事前に正確にキャプチャし、実際の結果と比較できるテスト技術である.テストターゲット機能の実装が変更され、実際の結果とスナップショットの予想結果とは異なる場合、テストケースは失敗します.この場合、新しいスナップショットを再起動して、既存のスナップショットを置き換え、スナップショットとテストコードを維持できます.
例えば、ある写真を撮るとします.撮る前に、頭の中の画像(仮説)を撮ります.そして写真を撮って、前に撮った脳の画像写真と比較します.異なる場合、テストケースは失敗します.既存のスナップショットを新しいスナップショットで置き換えて続行

inline snapshot by jest

// repeat.js

function repeat(word, times = 2) {
  let words = [];
  for (let i = 0; i < times; i++) {
    words.push(word);
  }
  return words;
}

export default repeat;
// repeat.test.js

import repeat from "./repeat";

test("repeats words three times", () => {
  expect(repeat("Test", 3)).toMatchInlineSnapshot();
});
このテストコードを実行すると、テスト・ケースが合格し、スナップショットが書き込まれたことを示すメッセージが表示されます.

では、このスナップショットはどこで作られたのでしょうか.
// repeat.test.js

import repeat from "./repeat";

test("repeats words three times", () => {
  expect(repeat("Test", 3)).toMatchInlineSnapshot(`
    Array [
      "Test",
      "Test",
      "Test",
    ]
  `);
});
以下に示すように、既存のファイルにインラインスナップショットが作成されています.Jestによって作られます.

Jestインラインスナップショットのリフレッシュ


既存のrepeat.jsファイルを置換
// repeat.js

function repeat(word, times = 2) {
  let words = [];
  for (let i = 0; i < times; i++) {
    words.push(word);
  }
  return words.join(); // 베열 대신 문자열 반환
}

export default repeat;
その後、テストを行います.もちろん、テストケースは失敗します.スナップショットとは異なります.

フィードバックの詳細は以下の通りです.-uオプションでjestを実行したら?
$ npx jest -u
// repeat.test.js

import repeat from "./repeat";

test("repeats words three times", () => {
  expect(repeat("Test", 3)).toMatchInlineSnapshot(`"Test,Test,Test"`);
});
スナップショットが更新されます.

インラインスナップショットを通常のテストとして使用

jestmatcher関数を使用できます.
// repeat.test.js

import repeat from "./repeat";

test("repeats words three times", () => {
  expect(repeat("Test", 3)).toEqual("Test,Test,Test");
});

File Snapshot by Jest


スナップショットが長い場合や複雑な場合は、スナップショットを別のファイルに配置するよりも、テストファイルにスナップショットを配置するほうが管理しやすいです.スナップショットを別のファイルとして管理します.
主にjesttoMatchSnapshot()が用いられる.
// repeat.test.js

import repeat from "./repeat";

test("repeats words three times", () => {
  expect(repeat("Test", 3)).toMatchSnapshot();
});
テストはスナップショットを生成します.テストファイルが存在するパスにスナップショットディレクトリを作成し、繰り返します.test.js.snapファイルが表示されます.
// Jest Snapshot v1, https://goo.gl/fbAQLP
// __snapshots__/repeat.test.js.snap## File Snapshot 갱신


exports[`repeats words three times 1`] = `"Test,Test,Test"`;

ファイルスナップショットのリフレッシュ


更新repeat.js、以下に示すように
// repeat.js

function repeat(word, times = 2) {
  let words = [];
  for (let i = 0; i < times; i++) {
    words.push(word);
  }
  return words; // 문자열 대신 배열 반환
}

export default repeat;
テストの実行に失敗しました.これはスナップショットとは異なります.
同様に、npm run jest -uを実行すると、スナップショットが再リフレッシュされます.
// __snapshots__/repeat.test.js.snap
exports[`repeats words three times 1`] = `
Array [
  "Test",
  "Test",
  "Test",
]
`;

整理する


また、Jestを使用して行内スナップショットとファイルスナップショットをテストする方法についても議論しました.スナップショットテストは、関数の予想される結果を直接符号化する必要はありませんが、不適切な使用などの副作用をもたらし、スナップショット自体のメンテナンスが困難になります.したがって、開発者がテストの予想結果を作成するのに多くの時間と労力を費やした場合にのみ使用することをお勧めします.
😆 任意の関数の予想結果を直接符号化する必要がない便利さがある.Jestは私たちのためにスナップショットを作成します.
😭 しかし、不適切な使用では、かえってメンテナンスが難しい.
自分が予想した結果を書くのに時間がかかると思ったら、書きましょう.

Reference

  • スナップショットのテスト