📖

TDDのTを作ってみました

2023/12/19に公開

mediba Advent Calendar 2023 23日目の記事です。
最近バックエンドでのテスト駆動開発(以下TDD)を体験したyangです。
バックエンド且つGOの初心者で、自信を持ってPRを出せる訳は「テストは全部通った」ですねw
今までフロントエンドではさまざまな理由でTDDをやっていなかったが、今回は言い訳なしで、
TDDをやっていきたいと思います!

作り

これから仮で作りたいものは、
ECサイトの商品リスト、機能は三つ

  • 商品リスト表示
  • 商品名で検索
  • 商品価額範囲で検索

TDDのサイクルを回すには、まずはテストコードを書くことです。
仕様が決まったら、普通?ではデザイナーさんからデザインをもらってから、開発を始めるが、今回は仕様だけでも進めるようにテストを書いてみます。
とはいえ、テストしたいものを明確にしなければならない、なので、現在テストで担保したいものは上記三つの機能ですね、それに機能を実現する最低限のコンポネートは下記のように

  • 商品リスト表示
    • リスト(product_list)
  • 商品名で検索
    • 商品名入力欄(name_search_input)
    • 検索ボタン(search_button)
  • 商品価格で検索
    • 商品価格範囲入力欄(price_search_input_min&max)
    • 検索ボタン(search_button)
      それぞれのコンポネートの存在確認していきます、
      ※今回のテストはjest@testing-library/reactでやります。
test('コンポネートの存在確認', () => {
  render(<MyProductList />); //仮コンポネート MyProductList
  expect(screen.getByTestId('product_list')).toBeInTheDocument();
  expect(screen.getByTestId('name_search_input')).toBeInTheDocument();
  expect(screen.getByTestId('search_button')).toBeInTheDocument();
  expect(screen.getByTestId('price_search_input_min')).toBeInTheDocument();
  expect(screen.getByTestId('price_search_input_max')).toBeInTheDocument();
});

それから三つの機能に関するテストは下記のように書きます。

// 仮商品データ
const products = [
  { id: 1, name: 'Chooclate', price: 1000 },
  { id: 2, name: 'Banaba', price: 898 },
  { id: 3, name: 'Carort', price: 354 },
  { id: 4, name: 'Paenats', price: 12 },
];

// 機能①
test('商品リスト表示', () => {
  render(<ProductList products={products} />);
  // 商品一つずつを表示しているか
  expect(screen.getAllByTestId('product')).toHaveLength(4);
  // 表示したい項目が表示されているか
  expect(screen.getByText(/Chooclate/i)).toBeInTheDocument();
  expect(screen.getByText(/¥1000/i)).toBeInTheDocument();
  expect(screen.getByText(/Banaba/i)).toBeInTheDocument();
  expect(screen.getByText(/¥898/i)).toBeInTheDocument();
  expect(screen.getByText(/Carort/i)).toBeInTheDocument();
  expect(screen.getByText(/¥354/i)).toBeInTheDocument();
  expect(screen.getByText(/Paenats/i)).toBeInTheDocument();
  expect(screen.getByText(/¥12/i)).toBeInTheDocument();
});

// 機能②
test('商品名で検索', () => {
  render(<ProductList products={products} />);
  // 入力エレメント取得
  const nameInput = screen.getByTestId('name_search_input');
  // 'a'で検索したら
  fireEvent.change(nameInput, { target: { value: 'a' } });
  // 商品名に'a'が入っている商品だけ表示されているか
  expect(screen.getAllByTestId('product')).toHaveLength(4);
  expect(screen.getByTestId('product_list')).toBeInTheDocument();
  expect(screen.getByText(/Chooclate/i)).toBeInTheDocument();
  expect(screen.getByText(/Banaba/i)).toBeInTheDocument();
  expect(screen.getByText(/Paenats/i)).toBeInTheDocument();
  expect(screen.getByText(/Carort/i)).toBeInTheDocument();
});

// 機能③
test('商品価額範囲で検索', () => {
  render(<ProductList products={products} />);
  // 価格範囲入力エレメント取得
  const minPriceInput = screen.getByTestId('price_search_input_min');
  const maxPriceInput = screen.getByTestId('price_search_input_max');
  // '400'で最小価格に設定
  fireEvent.change(minPriceInput, { target: { value: '400' } });
  // 値段が400円以上も商品が表示さているか
  expect(screen.getAllByTestId('product')).toHaveLength(2);
  expect(screen.getByText(/Chooclate/i)).toBeInTheDocument();
  expect(screen.getByText(/Banaba/i)).toBeInTheDocument();
  expect(screen.queryByText(/Carort/i)).not.toBeInTheDocument();
  expect(screen.queryByText(/Paenats/i)).not.toBeInTheDocument();
  // '900'で最大価格に設定
  fireEvent.change(maxPriceInput, { target: { value: '900' } });
  // 値段が400円以上且900円以下も商品が表示さているか
  expect(screen.getAllByTestId('product')).toHaveLength(1);
  expect(screen.queryByText(/Chooclate/i)).not.toBeInTheDocument();
  expect(screen.queryByText(/Carort/i)).not.toBeInTheDocument();
  expect(screen.queryByText(/Paenats/i)).not.toBeInTheDocument();
  expect(screen.getByText(/Banaba/i)).toBeInTheDocument();
});

これでテストコードが完成しました。

感想

今までと違って、書いたコードの上でテストを作成するではなく、仕様をコード化にしものであります。
自然に仕様通りに動くかというテストになり、そもそも開発はこれからのものだから、実装の詳細をテストするようなことになりません。
これからもこいう風にTDDをやっていきたいという気持ちです。

上記のテストで作ってみた投稿お待ちしております

参考:
[1] 《When I follow TDD》: https://kentcdodds.com/blog/when-i-follow-tdd

[2] Testing Library: https://testing-library.com/

猫自慢

Discussion