課題-1 / test 古の記法を現代風に書き換えました。関数をテストしていきます。
index.test.jsを作り前回のコードをインポートして、Jestでテストします。
nodemonをルートで使っているので、Jestもルートから使います。
Jestのインストールですが、
npm install --save-dev jestjsonのスクリプトには
"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 totalannounceMockの回数と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手軽に関数がチェックできるのは素晴らしいです。
