みなさん、テストコードはちゃんと書いてますでしょうか?
私は今回アサインされたプロダクトで初めて書きました
テストを書くことがなんか大切であることはわかるけど、
書く時間がない...なんか難しそう...って思う人もいるかもしれません。
自分は正直、思ってました。笑
でも実は、ただの「確かめ算」をしているだけでそこまで難しくない & それ以上に大きなメリットがある、と
テスト書き始めて2ヶ月程度で気づき始めました。
そんなテスト初心者の自分が、テストの素晴らしさを力説しようと思います
そもそもなんでテストを書くの?
自分たちが書いたコードがちゃんと正しく動き続けることを保証するため
プロダクト開発する上で、こんなことが起きちゃったりしていませんか?
「このパターンの場合、このロジックでは正しく動きません!!!」
→ このパターンのテストを書いてちゃんと検証しておけばなぁ。
「Cちゃんがコードを改修したら、このロジックが壊れました...」
→ ちゃんとテスト書いておけば、テストが通らないから気づけたのになぁ。
基本、コードは正しく動き続けることは保証できません。人間の心と同じく脆いです(白目)
一方でテストを書くことで、不安なパターンを事前にチェックしておくことができたり、
壊れたタイミングで知ることができたりするので、「正しく動き続けることを保証」をすることができます。
どんな処理であるか共同開発者に伝える、ドキュメント的な役割
例えば、下記のような「ぱっと見じゃようわからん処理」があったとします。
export const filteredArray = <T>(a: T[], b: T[]): T[] => {
return a.filter((a) => b.some((b) => b === a));
};
テストを書きましょう。
describe('filteredArray', () => {
test('配列aと配列bが一致している要素を取り出す', () => {
const dummyArrayA = ['a', 'b', 'c', 'd'];
const dummyArrayB = ['c', 'd', 'e', 'f'];
expect(filteredArray(dummyArrayA, dummyArrayB)).toEqual(['c', 'd']);
});
});
ああ、この処理は「配列aと配列bが一致している要素を取り出す」ものなんだ。ってことが一目瞭然です。
今回の例はシンプルな処理ではありましたが、
もっと複雑な処理や複雑な、パターンの処理がある時に、
コードを読まなくとも、テストでどのような処理かを伝えることができます。
コードの責務が正しいか確認するため
「なんかこのコードテストが書きづらいぞ...」ってなった時は、そもそもコードが正しい責務で書かれていない可能性があります。
そのため、テストは処理を見直す機会も与えてくれます。
テストを書くフロー
0. テストファイルの作成
検証したいロジックのある同階層に、同じファイル名で〇〇.spec.js
/〇〇.test.js
というファイル (もちろん.ts
でも可)を作成します。
1. コードをひとことで言語化
describe
という名前づけ関数を用いて、コードの責務を言語化していきます。
describe("名前", () => { 処理 })
describe
は入れ子にできるため、自分はテストを書く時は下記のように書きます。
describe('関数名', () => {
describe('その処理を一言で説明', () => {
//
})
})
2. テストケースを網羅させる
test
もしくはit
というテストケースを書く関数を用いて、パターンの洗い出しを行います。
test("テストケース", () => { 検証 }) // 日本語okなのでこっち使いがち。
it("テストケース", () => { 検証 }) // itは「振る舞い」という意味合い。そのため、基本英語で書いたりする。
基本的には、「分岐が発生した場合全てのパターン」に対して、書きます。
describe('関数名', () => {
describe('その処理を一言で説明', () => {
test('〇〇の時、××', () => {
// 検証
})
test('△△の時、◻︎◻︎', () => {
// 検証
})
})
})
3. 正しい挙動をしているか確認
expect
というテスト対象を指定関数を使って、正しい挙動をしているか確認します。
expect
は、検証したい内容に合わせてテストマッチャーをチェーンさせていきます。
//値が一致してるか
expect(テスト対象).toEqual(値);
//値が一致していないか
expect(テスト対象).not.toEqual(値);
1つのtest
/ it
には必ず 一つのexpect
が必要です。
describe('関数名', () => {
describe('その処理を一言で説明', () => {
test('〇〇の時、××', () => {
expect(テスト対象).toEqual(値);
})
test('△△の時、◻︎◻︎', () => {
expect(テスト対象).not.toEqual(値);
})
})
})
テストマッチャーの種類は非常に多く覚えるのが大変であるため、自分は下記の逆引き記事を見て
自分のテストしたいものに合うものを探して使っています!
以上、テストの書き方でした!!
明日はhooksのテストの書き方に関してです!!