見出し画像

課題-1 / test 古の記法を現代風に書き換えました。関数をテストしていきます。

index.test.jsを作り前回のコードをインポートして、Jestでテストします。
nodemonをルートで使っているので、Jestもルートから使います。
Jestのインストールですが、

npm install --save-dev jest

jsonのスクリプトには

"test": "jest --watch --verbose --runInBand projects/from-javascript-to-typescript/the-typeinator/01-syntactic-sugar/index.test.js",
  • --watch
    → ファイル変更を監視して、保存したら自動でテスト再実行

  • --verbose
    → どのテストが通ったか・落ちたかを詳しく表示

  • --runInBand
    → テストを並列実行せず1つずつ順番に実行(デバッグ用・安定重視)


テストをするコード

function announceMachines(announce, ...machines) {
	let label;
	let labelCount = 0;
	for (let mashine of machines) {
		if (mashine.label) {
			label = mashine.label;
			labelCount++;
		} else {
			label = `make:${mashine.make},model:${mashine.model}`;
		}
		announce(label);
	}
	return labelCount;
}

const announcedLabels = announceMachines(console.log , ...machines)

console.log(`ラベルの合計の数${announcedLabels}`);

テストコード

const { announceMachines } = require("./solution");

describe("announceMachines", () => {///説明
	it("logs each machine label and returns label count", () => {
		const announceMock = jest.fn();//記録
		const machines = [
			{ make: "Acme", model: "X1" },
			{ label: "Custom-Turbo-2000" },
			{ make: "OmniCorp", model: "A12" },
			{ label: "HyperDrive-9000" },
			{ make: "Acme", model: "X2" },
		];

		const count = announceMachines(announceMock, ...machines);
		const expectedLabelCount = machines.filter(
			(machine) => machine.label,
		).length;
		const expectedLabels = machines.map((machine) =>
			machine.label
				? machine.label
				: `Make: ${machine.make}; Model: ${machine.model}`,
		);

		expect(count).toBe(expectedLabelCount); // label プロパティがあるのは1件
        expect(announceMock).toHaveBeenNthCalledWith(2, "Custom-Turbo-2000");
		expect(announceMock).toHaveBeenCalledTimes(expectedLabels.length);
		expectedLabels.forEach((label, index) => {
			expect(announceMock).toHaveBeenNthCalledWith(index + 1, label);
		});
		console.log(announceMock.mock.calls);
	});
});

Jestを使うのは初めてなので、色々メモしていきます。

・describe("ここには関数をセットします" , ( ) => { …/ } )

・it("出力、マシーンのラベル、リターンラベルカウント" , ( ) => { …/ } )
itは詳細説明です。

・const announceMock = jest.fn( )
アナウンスをMockに置き換えます。jest.fn( )は呼び出し履歴を全部記録する関数。最後コンソールで呼び出すため、何回呼ばれたか、何回目の引数かがわかります。
Mockとは偽物という意味です。

・const expectedLabelCount = machines.filter( (machines) => machine.label,).length; フィルターでtrueを返した要素の数をだし、ラベルの合計数を出していきます。

・const expectedLabels = machines.map( (machine) => machine.label ? machine.label : `Make: ${machine.make}; Model: ${machine.model}`,);  マシーンラベルであれば、マシーンラベル ちがければ、makeとmodelのテンプレートリテラルに当てはめていきます。mapの出力結果は配列の中に、要素を入れていきます。マシーンラベルを出します。

map例
["Make: Acme; Model: X1","Custom-Turbo-2000","Make: Zenith; Model: Z5"]

・expect() 値をテストする。

・expect(a).toBe(b) aとbが必ず同じである。

・expected(Mock).toHaveBeenCalledTimes(3)モックは3回呼ばれたか。

・expected(Mock).toHaveBeenNthCalledWith(index + 1 ,label )indexは何回目の呼び出しかを引数にとり、labelは値です。

・console.log(announceMock.mock.calls);モックが何回呼ばれたか記録を書き出します。announceMock = jest.fn()でモック関数が作られる。.mock.callsが記録する。toHaveBeenTimesなどがそれを読む。


テスト開始

まずコンソールを出力してみます。

console.log(announceMock.mock.calls);

  console.log
    [
      [ 'Make: Acme; Model: X1' ],
      [ 'Custom-Turbo-2000' ],
      [ 'Make: OmniCorp; Model: A12' ],
      [ 'HyperDrive-9000' ],
      [ 'Make: Acme; Model: X2' ]
    ]

count = 返り値は2 announceMachinesの返り値2です。
合格しました。

expect(count).toBe(expectedLabelCount);
 PASS  projects/from-javascript-to-typescript/the-typeinator/01-syntactic-sugar/index.test.js
  announceMachines
    ✓ logs each machine label and returns label count (3 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total

announceMockの回数とexpectedLabels.lengthの数か同じかを見ていきます。何度も怒られながらも合格しました。

expect(announceMock).toHaveBeenCalledTimes(expectedLabels.length);

一応エラーが起きるとこうなります。
lengthが抜けている場合です。

announceMachines › logs each machine label and returns label count

    expect(received).toHaveBeenCalledTimes(expected)

    Matcher error: expected value must be a non-negative integer

    Expected has type:  array
    Expected has value: ["Make: Acme; Model: X1", "Custom-Turbo-2000", "Make: OmniCorp; Model: A12", "HyperDrive-9000", "Make: Acme; Model: X2"]

      55 |              );
      56 |              expect(count).toBe(expectedLabelCount);
    > 57 |              expect(announceMock).toHaveBeenCalledTimes(expectedLabels);
         |                                   ^
      58 |              console.log(announceMock.mock.calls);
      59 |      });
      60 | });


toHaveBeenNthCalledWithを使って、キーとラベルのセットが、n回目まで同じか見ていきます。

expectedLabels.forEach((label, index) =>
	expect(announceMock).toHaveBeenNthCalledWith(index + 1, label),
);

こちらも大丈夫でした。
2回目に同じ値が来ているかもチェックします。

expect(announceMock).toHaveBeenNthCalledWith(2, "Custom-Turbo-2000");
 PASS  projects/from-javascript-to-typescript/the-typeinator/01-syntactic-sugar/index.test.js
  announceMachines
    ✓ logs each machine label and returns label count (21 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.251 s, estimated 1 s


手軽に関数がチェックできるのは素晴らしいです。

いいなと思ったら応援しよう!