Jestチュートリアル入門: JavaScriptテスト用Jestの始め方
dev.toでフォロワーが5千人を超えました!ありがとうございます!素晴らしいコミュニティですね!Twitterも使ってる人いますか?繋がりましょう => 私はこちら。
テストとは何か? Jestを使ってJavaScriptのコードをどうテストするの?このJest初心者チュートリアルでJavaScriptの基本的なテストの方法を学びましょう!
テストとは何か?
テックの業界用語では、テストは私たちのコードがある期待に合致しているか確認することを意味します。例えば、「トランスフォーマー」という関数は、ある入力に対して期待される出力を返すべきです。
テストには多くの種類があり、あなたはすぐにその専門用語に圧倒されるでしょうが、端的に言うと、テストは主に3つのカテゴリーに分けられます:
- 単体テスト
- 統合テスト
- UIテスト
このJestチュートリアルでは単体テストのみをカバーしますが、記事の最後に他のテストの種類についての資料も見つけられます。
Jestチュートリアル: Jestとは何か?
JestはJavaScriptテストランナー、つまり、テストの作成、実行、および構造化を行うためのJavaScriptライブラリです。JestはNPMパッケージとして配布されており、JavaScriptプロジェクトにインストールすることができます。Jestは現在最も人気のあるテストランナーの一つであり、Create React Appのデフォルトの選択肢です。
最初の段階: 何をテストすればいいのかどうやって知るの?
テストに関しては、初心者は単純なコードのブロックでさえも困惑させることがあります。最も一般的な疑問は**「何をテストすればいいの?」です。もしあなたがウェブアプリケーションを書いているなら、アプリのすべてのページと全てのユーザーインタラクションをテストすることが良い出発点になります。しかし、ウェブアプリケーションは関数やモジュールといったコードの単位**も含まれており、それらもテストする必要があります。大体の場合は2つのシナリオがあります:
- テスト無しでレガシーコードを引き継ぐ場合
- 空から突然新しい機能を実装しなければならない場合
どうすべきでしょうか?両方のケースについて考えるべきなのが、テストをある関数が期待された結果を生産するか確認するコードのかけらと考えることです。典型的なテストの流れはこんな感じです:
- テストする関数をインポートする
- 関数に入力を与える
- 出力として何を期待するか定義する
- 関数が期待された出力を生産するか確認する
本当にそれだけです。入力 - 期待される出力 - 結果をアサートするという観点で考えるなら、テストはもう怖くないでしょう。すぐに、何をテストすべきかほぼ確実にチェックできる便利なツールも見ていきます。そして、それではJestについて学びましょう!
Jestチュートリアル: プロジェクトのセットアップ
すべてのJavaScriptプロジェクトと同様に、NPM環境が必要です(システムにNodeがインストールされていることを確認してください)。新しいフォルダを作成し、以下のコマンドでプロジェクトを初期化してください:
mkdir getting-started-with-jest && cd $_
npm init -y
次に、以下のコマンドでJestをインストールします:
npm i jest --save-dev
コマンドラインからテストを実行できるように、package.jsonを開いて"test"というスクリプトを設定してJestを実行できるようにします:
"scripts": {
"test": "jest"
},
これで準備は完了です!
Jestチュートリアル: 仕様とテスト駆動開発
私たち開発者は創造の自由が大好きです。しかし、真剣なことになると、そんなに特権はありません。よくあることですが、私たちは仕様に従わなくてはなりません。つまり、何を構築すべきかの書面あるいは口頭の説明です。
このチュートリアルでは、プロジェクトマネージャーから比較的シンプルな仕様が出ています。非常に重要なクライアントが、オブジェクトの配列をフィルターするJavaScript関数が必要です。
各オブジェクトには"url"というプロパティがあり、そのプロパティの値が特定の用語と一致する場合に限り、そのオブジェクトを結果の配列に含める必要があります。テストに詳しいJavaScript開発者として、コードを書き始める前に失敗するテストを書くという、テスト駆動開発という規律に従いたいと思います。
デフォルトではJestはプロジェクトフォルダ内のtestsというフォルダにあるテストファイルを検索します。新しいフォルダを作成しましょう:
cd getting-started-with-jest
mkdir __tests__
次に、tests内にfilterByTerm.spec.jsという新しいファイルを作成します。".spec."という拡張子が含まれている理由は、Rubyの慣習を借りて、そのファイルが特定の機能の仕様を印すためです。
さあ、テストを始めましょう!
Jestチュートリアル: テストの構造と最初の失敗するテスト
初めてのJestテストを作成する時が来ました。filterByTerm.spec.jsを開き、テストブロックを作成してください:
describe("Filter function", () => {
// test stuff
});
私たちの最初の友達はdescribeで、関連するテストが1つ以上含まれるJestのメソッドです。新しいテストスイートを書き始めるときはいつでも、それをdescribeブロックで包むようにします。ご覧の通り、テストスイートを説明する文字列と、実際のテストを包むコールバック関数という2つの引数が取られます。
次に、testというもう1つの関数に出会います。これが実際のテストブロックです:
describe("Filter function", () => {
test("it should filter by a search term (link)", () => {
// actual test
});
});
これで、テストを書く準備ができました。覚えておいてください、テストは入力、関数、見込まれる出力の問題です。まずはシンプルな入力、つまりオブジェクトの配列を定義しましょう:
describe("Filter function", () => {
test("it should filter by a search term (link)", () => {
const input = [
{ id: 1, url: "https://www.url1.dev" },
{ id: 2, url: "https://www.url2.dev" },
{ id: 3, url: "https://www.link3.dev" }
];
});
});
次に、見込まれる結果を定義しましょう。仕様によると、テスト対象の機能は、与えられた検索用語と一致しないurlプロパティを持つオブジェクトを除外するべきです。例えば、検索用語に"link"を与えた場合、予想される配列は1つのオブジェクトだけです:
describe("Filter function", () => {
test("it should filter by a search term (link)", () => {
const input = [
{ id: 1, url: "https://www.url1.dev" },
{ id: 2, url: "https://www.url2.dev" },
{ id: 3, url: "https://www.link3.dev" }
];
const output = [{ id: 3, url: "https://www.link3.dev" }];
});
});
これで、実際のテストを書く準備が整いました。私たちはJestのmatcherとexpectを使って、現在架空の(今のところ)関数が呼び出されたときに、期待される結果を返すかをチェックします。テストはこうなります:
expect(filterByTerm(input, "link")).toEqual(output);
さらに細かく分解すると、コード内で関数を次のように呼び出すところです:
filterByTerm(inputArr, "link");
Jestのテストでは、expect内に関数の呼び出しを包むべきであり、matcher(Jestで出力をチェックする関数)と組み合わせることで、実際のテストになります。以下が完全なテストです:
describe("Filter function", () => {
test("it should filter by a search term (link)", () => {
const input = [
{ id: 1, url: "https://www.url1.dev" },
{ id: 2, url: "https://www.url2.dev" },
{ id: 3, url: "https://www.link3.dev" }
];
const output = [{ id: 3, url: "https://www.link3.dev" }];
expect(filterByTerm(input, "link")).toEqual(output);
});
});
(さらにJestのmatcherについて学びたい場合は、ドキュメントをご覧ください)
これで以下のコマンドを実行し、テストを試してみることができます:
npm test
すると、テストが見事に失敗するのを見ることができます:
FAIL __tests__/filterByTerm.spec.js
Filter function
✕ it should filter by a search term (2ms)
● Filter function › it should filter by a search term (link)
ReferenceError: filterByTerm is not defined
9 | const output = [{ id: 3, url: "https://www.link3.dev" }];
10 |
> 11 | expect(filterByTerm(input, "link")).toEqual(output);
| ^
12 | });
13 | });
14 |
「ReferenceError: filterByTerm is not defined」実際、それは良いことです。次のセクションで修正しましょう!
Jestチュートリアル: テストの修正(と再び壊す)
実際に欠けているのはfilterByTermの実装です。便宜上、テストファイルと同じファイルに関数を作成することにします。実際のプロジェクトでは、関数を別のファイルに定義し、それをテストファイルからインポートするでしょう。
テストを合格させるために、ネイティブのJavaScript関数である**filter** を使用して、配列から要素をフィルタリングします。こちらがfilterByTermの最小実装です:
function filterByTerm(inputArr, searchTerm) {
return inputArr.filter(function(arrayElement) {
return arrayElement.url.match(searchTerm);
});
}
それがどのように機能するかは、入力配列の各要素の"url"プロパティをチェックし、**match**メソッドで正規表現に一致させることです。以下が完全なコードです:
function filterByTerm(inputArr, searchTerm) {
return inputArr.filter(function(arrayElement) {
return arrayElement.url.match(searchTerm);
});
}
describe("Filter function", () => {
test("it should filter by a search term (link)", () => {
const input = [
{ id: 1, url: "https://www.url1.dev" },
{ id: 2, url: "https://www.url2.dev" },
{ id: 3, url: "https://www.link3.dev" }
];
const output = [{ id: 3, url: "https://www.link3.dev" }];
expect(filterByTerm(input, "link")).toEqual(output);
});
});
テストを再度実行してください:
npm test
合格しているのを見ることができます!
PASS __tests__/filterByTerm.spec.js
Filter function
✓ it should filter by<br><br>こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。<br>[https://dev.to/valentinogagliardi/jest-tutorial-for-beginners-getting-started-with-jest-for-javascript-testing-e6c](https://dev.to/valentinogagliardi/jest-tutorial-for-beginners-getting-started-with-jest-for-javascript-testing-e6c)