21
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

みなさん、テストコードはちゃんと書いてますでしょうか?
私は今回アサインされたプロダクトで初めて書きました :dizzy_face: :dizzy_face:

テストを書くことがなんか大切であることはわかるけど、
書く時間がない...なんか難しそう...って思う人もいるかもしれません。
自分は正直、思ってました。笑

でも実は、ただの「確かめ算」をしているだけでそこまで難しくない & それ以上に大きなメリットがある、と
テスト書き始めて2ヶ月程度で気づき始めました。

そんなテスト初心者の自分が、テストの素晴らしさを力説しようと思います:muscle_tone1:

そもそもなんでテストを書くの?

自分たちが書いたコードがちゃんと正しく動き続けることを保証するため

プロダクト開発する上で、こんなことが起きちゃったりしていませんか?

:scream: 「このパターンの場合、このロジックでは正しく動きません!!!」
  → このパターンのテストを書いてちゃんと検証しておけばなぁ。

:fearful: 「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のテストの書き方に関してです!!

21
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?