持続可能なフロントエンドのテストコードを書くために大切にしていること

こんにちは、kintone フロントエンドリアーキテクチャプロジェクト(フロリア)でエンジニアをしているはた丸です。

昨今は何かとSDGsが話題になる世の中なので、フロントエンドのテストコードも持続可能なものを作っていきたいと考えています。

この記事ではフロリアのチームの1つであるMiraチームがテストを自動化するうえで意識していることをお伝えします。

自分のチームに自動テストを導入できるか不安な方、導入後に継続できるか心配な方に寄り添えると嬉しいです。

はじめに、Miraチームの概要やテスト手法の全体像について知りたい方は、次の記事をご覧ください。


目次


📝 前提

フロリアでは主に React と Testing Library を利用しており、記事内で紹介する記述には同様の技術スタックを前提としたものがあります。

♻️ Integrationテストをがんばる

MiraチームではTesting Trophyの考え方に沿ってテストの方針を決めており、Integrationテストの比重を大きくしています。

Testing Trophyではテストの重要性や優先順位をトロフィーの形で表現しており、その中で開発コストに対する品質保証面のコスパが優れているIntegrationテストの重要性について紹介されています。

詳細については上記ブログをご覧いただきたく、ここではIntegrationテストの自動化に効率的に取り組むために、Miraチームで体感したTipsをご紹介します。

a11yを意識した実装をしておく

Integrationテストの実装時に苦労することの1つに、画面の奥底にある要素を取得するためにコードや画面をいったりきたりしながら試行錯誤を繰り返す、ということがあります。

しかし、機能実装時にあらかじめa11yを意識して構築しておけば、Testing Libraryで推奨される getByRole による要素取得を活用できるようになります。

// ダイアログが表示されている
const dialog = screen.getByRole('dialog')
expect(dialog).toBeInTheDocument();

// ダイアログの中身の表示確認
const title = within(dialog).getByRole('heading', { level: 2 });
expect(title).toHaveTextContent('cybozu');
const closeButton = within(dialog).getByRole('button', { name: 'close' });
expect(closeButton).toBeInTheDocument();

ヘルパー関数を用意する

といっても、それでも取得するのに苦労する要素はあります。そんなときはヘルパー関数を用意しましょう。苦労するのは、はじめに頑張ったあなただけで十分です。

同様にページ共通で使う要素なども積極的に切り出しておきましょう。

このような共通化や再利用性の向上は、後述のQAとの協調においても助けになります。

/** Notificationを得る */
export const getNotifier = () => screen.getByTestId('Notifier');

/** Notificationの閉じるボタンを得る */
export const getNotifierCloseBtn = () =>
  within(getNotifier()).getByRole('button', { name: 'close' });

QAとエンジニアで協調する

フロリアでは、QAと実装者が協力する形でIntegrationテストの設計・実装・レビューを進めています。逆にUnitテストにおいては、単一のコンポーネントやhooksを対象とするため、実装者の裁量に一任しています。

上記ブログに詳細なプロセスが書かれていますが、特に重要と考えるのは

  • 機能実装前にIntegrationテストの設計(ケース策定)が完成している
  • テスト設計にエンジニアも参加している
  • テストコードレビューにQAも参加している

の3点です。フロリアでは実装から不具合発見までのフィードバックを早くすることを目標にし、手戻りを減らすことを心がけています。 そのためにはエンジニアが実装と同時にIntegrationテストの自動化に取り組み、実装直後にQAからフィードバックを得られる仕組みが大切だと考えています。

♻️ E2Eテストをがんばりすぎない

Miraチームでは、正常系の基本的なユースケースのフローを確認する「ハッピーパス」の方針で、E2Eテストを自動化しています。また、Integrationテストで充足すると考えられるE2Eのケースは排除し、E2Eテストをスリム化しています。

もしかすると、これからテストの自動化に取り組もうとしているチームでは、「とりあえずE2Eテストからはじめよう」と考えている方がいるかもしれませんが、おすすめはできません。

実はkintoneの開発でも、これまではE2Eでの自動テストとQAによる手動テストが主でしたが、いくつか課題がありました。

  • 実行に時間がかかるためCIを継続・反復しづらい
  • 実装してからフィードバックを得るまでに時間がかかる
  • メンテナンスコストが高い

これらに対する対策として、フロリアではIntegrationテストを重視する方針を立てています。

「それでもチームナレッジを貯めるためにどうしてもブラウザテストから始めていきたい!」という場合はリグレッションテストなど、ケース数が少なく、将来的にも肥大化しづらいものを対象としてスタートしていくことをおすすめします。

おわりに

今回紹介した内容の他にもフロリアでは様々なテストナレッジが溜まっています。テストカテゴリの他の記事もぜひご覧ください!

サイボウズではフロントエンドエンジニアを募集しています。