テスト自動化のはじめの一歩 ~テストコードの導入~

# テストの自動化に動く

スタートアップやベンチャー企業では、新しいサービスの開発とその普及に力を注ぐことが一般的です。この過程では、新機能の追加や新サービスのリリースが頻繁に行われることがあります。ビジネスの成長に伴い、少々のバグを許容することも、時には避けられない戦略かもしれません（理想的ではありませんが）。しかし、サービスが成長し複雑になるにつれて、バグは避けられず発生します。このような状況が続くと、会社はようやく保守や運用に注目し、メンテナンスへの意識が高まります。

会社でテストプロセスを自動化するためには、まずエンジニアが手動ではなく自動テストを行う文化を育てることが大切です。以前、私はある会社で、フロントエンドからバックエンドに至るまで、テストコードやテスト規約、テスト方法を作成しました。これらの経験に基づき、テストコード導入のための「テストコード規約」を定める際の重要なポイントを共有して、参考にしていただければと思います。


# テストコードの導入するきっかけ
テストコードの導入には、何かしらのきっかけが必要かもしれません。それはネガティブなことが多いでしょう。

- あるエンジニアが全くコメントを書かないし、何をしている処理なのかわからないため理解しにくい
- 新卒や新人のエンジニアが入ってきた時に、APIやバッチなどのコードや処理の理解がしにくい
- インシデントが多発していて、メンテナンスに問題がある

こういった内容が予想されますが、これらのネガティブはむしろ社内の技術レベルやサービスレベルを上げるチャンスです。テストコードの導入は手動を挟まないために、しっかりと書けば、品質担保や開発工数なども長期的にポジティブな方向に変換できます。ただ、そもそも俗にいうシステムにおけるテストも、単体テストや結合テストから、機能テスト、性能テスト、負荷テスト、回帰テスト、はたまたバリデーションテストなど言い方や種類はさまざまでどれがどれだかわかりにくいのが現状です。


# テストコードを導入するためのドキュメントの作成ステップ

テストコードを導入、自動テストを導入するための本当に最初のステップ5段階に分けて説明していきます。（0番目は、人の知識レベルによるため、数えないものとします。）

0. テストについて雑多に情報を集める
1. 社内の状況を把握し尽くす
2. テストの方針・指向を決める
3. 規約やルールブックのドキュメントの作成
4. フィードバック大会の開催

## 0. テストについて雑多に情報を集める

自分の開発環境の言語やフレームワークについてのテストについての雑多な情報を集めました。様々な記事を読ませていただき、参考になる部分などをまとめて知見を貯めました。
貯め方は以下リンクのZennのスクラップを使っていきました。画像のように、１記事に対して、簡単にまとめて、使えそうな部分などのメモを残していきました。これをしておくと実際に何か他の人からの質問があった時に使えます。

https://zenn.dev/jin237/scraps/327c5e400ec3f5

![Screenshot 2023-12-13 at 23.29.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556108/21d6cdc9-ca81-fe7b-3aae-92641c3a547f.png)



## 1. 社内の状況を把握し尽くす

**まずは、会社の現状を知り、それに合うテスト方針や指向を決めていくことが重要になってきます**

社内の現状のサービスや開発プロセスなどをまずは把握しておきましょう。さまざまな会社に聞いてみても共通するところは多いかもしれませんが、その会社ごとのスタイルや環境があるので、固定的にこれがいい！とは言えません。そこで、私は以下の項目を中心に社内の把握をしました。

||項目|内容|
|:--:|:---|:------|
|1|開発サービスの概要|会社のサービスの性質を理解することこそが最初のステップです。提供されるサービスの種類、複雑さ、顧客基盤を理解することで、必要なテストの厳密さを見極めることができます。|
|2|開発言語と<br>フレームワーク|会社で使用されているプログラミング言語とフレームワークを把握しなければ、テストアプローチが適切ではなくなります。異なる言語やフレームワークには、テストのためのベストプラクティスとツールがあります。|
|3|現在の開発課題と<br>保守プロジェクト|会社の開発プロセスにおける現在の課題、例えばボトルネック、繰り返し発生するバグ、技術的負債を評価することが重要です。保守プロジェクトの量も、テストのワークロードを決定する上で重要な役割を果たします。|
|4|システム開発の<br>ワークフロー|要件収集からデプロイまでのワークフローを理解することで、テストプロセスを最も効果的に統合または最適化できる段階を特定できます。|
|5|インシデント量の分析|内部および外部のインシデント報告は、改善の潜在的な領域と現在のテスト戦略の有効性についての洞察を提供します。|
|6|現在のテスト努力|現在テストに割かれている労力を評価することで、リソース割り当ての概念と、この分野へのさらなる投資の必要性が理解できます。|
|7|既存のテストコードの分析|テストコードが既に存在する企業では、これらのコードの品質、カバレッジ、および遵守されているコーディング標準をレビューすることで、改善が必要な領域や開発チームの潜在的なトレーニングニーズを特定するのに役立ちます。|


これらを把握するだけでも結構な時間はかかりますが、全てにおいてかなり重要な要素となります。これらを把握した上で、テストのまずは方針を決めることからやりましょう。



## 2. テストの方針・指向を決める
テストをするための考え方として、私はメルカリのテスト指向を参考にしました。「[テストコードの改革を進めている話](https://engineering.mercari.com/blog/entry/20230623-f8bcbed100/)」という記事を要約すると以下のようになります。


> 複雑なマイクロサービス環境におけるテストコード改革の課題とアプローチについての記事。
複雑なデータフローやバッチ処理を伴うサービスにおける品質の確保や、既存の機能を破壊しかねないコード変更に対するテストコードの必要性といった問題を取り上げている。チームは、テストをユニットテスト、コンポーネントテスト、インテグレーションテストに分類し、それぞれの範囲と責任を明確にすることに重点を置いている。また、一貫したテストの書き方や、テーブル駆動のテストを使用することの重要性も強調している。目標は、チームのテストに対する理解とアプローチを一致させ、最終的に品質向上とシステム再構築の成功に貢献することである。

### メルカリにおけるテストの3つのレイヤー
メルカリの以下のようなテストを3つのレイヤーに分けたピラミッドは、googleの昔のテスト指向をもとに、効率とカバレッジを向上させる構造化され、明示的にわかりやすいようにしたものです。

![メルカリのテストレイヤー](https://storage.googleapis.com/prd-engineering-asset/2023/06/b14e04a0-pyramid.jpg)

- ユニットテスト: このテストはピラミッドの基礎です。個々のコードユニットに焦点を当て、それぞれが単独で正しく機能することを保証します。
- コンポーネントテスト: 中間層で、ユニットテストより大きく、全アプリケーションより小さいコンポーネントをテストします。コンポーネントのインターフェースと外部要素との相互作用をテストします。
- インテグレーションテスト: ピラミッドの頂点に位置し、異なるコンポーネントがどのように協調して動作するかを評価し、統合システムが必要な機能を満たしていることを保証します。


### メルカリのアプローチをもとにカスタマイズ
メルカリのアプローチは、テストを構造化する唯一の方法ではありません。そのため、絶対的にこれが正しいとは言い切ることはできません。しかしながら、これを基礎に自分の会社にカスタマイズすることでもしかするとさらに効率的なあなたの会社ならでは圧倒的に効率的なテストができるかもしれません。

- **現在のテストフレームワークを分析する**：<br>現在の実践を評価し、メルカリのアプローチで埋めることができるギャップを特定します。
- **開発チームを教育する**：<br>チームがテストの異なるレイヤーを理解し、それらをどのように実装するかを把握することを確認します。
- **小規模から開始する**：<br>このアプローチを小さなプロジェクトに適用し始め、会社全体に展開する前に行います。
- **反復して適応する**：<br>フィードバックを使用してアプローチを微調整し、あなたの会社の独自の課題とニーズに適応させます。


# 3. 規約やルールブックのドキュメントの作成

これらの共通認識を図るためには、何かしらの文書化しておくことが必要です。githubのwikiやgoogle documentで作成することをお勧めしています。この理由は、バージョン管理ができることやどのように更新したのかをみることができるからです。別の媒体でも何かしらおすすめがあれば、教えてください（笑）

ドキュメントとしてまとめることとしては、基本的に以下の項目です。


|項目|内容|
|:--|:----|
|はじめに|ドキュメントの目的とテストコード規約の概要を説明する|
|テストの範囲と目的|どのようなテストがこの規約に含まれるのか、そのテストが目指す目的や目標を明確にする|
|テストの原則|テストコードを書く際に従うべき基本的な原則<br>例えば、独立性、再現性、明確さなど|
|テストレベルと種類<br>（テスト指向や方針など）|ユニットテスト、インテグレーションテスト、システムテストなど、各テストレベルの定義とその特徴|
|テスト環境|テストを実行するための環境設定に関するガイドライン|
|テストデータの管理|テストデータの作成、管理、および破棄に関する規約|
|命名規則|テストケースやテストメソッドの命名に関する規則|
|テストの構|テストコードの基本的な構造やフォーマットに関する指示|
|アサーションの使用|アサーション（テストの検証部分）の書き方と使い方|
|例外処理|テスト中の例外やエラーをどのように扱うか|
|ドキュメンテーションとコメント|テストコードに必要なコメントやドキュメンテーションのガイドライン|
|コードレビューと保守|テストコードのレビュープロセスと保守に関するポリシー|
|ツールとフレームワーク|使用するテストツールやフレームワークに関する情報|
|パフォーマンスと最適化|テストの実行速度やリソース使用の最適化に関する指針|
|セキュリティとプライバシー|テストプロセスにおけるセキュリティとプライバシーに関する考慮事項|
|付録|用語集、参考文献、サンプルコードなどの追加リソース|


# 4. フィードバック大会の開催

テストコードを書いている時には、調べたり、実際の現場の声を聞いたりすることは大切ですが、それだけでは足りません。フィードバック大会を開催することをお勧めします。
簡単なクソみたいなCRUDアプリを作成した上で、実際にどういうふうに使えるのかをデモで見せることでイメージがつきやすくなります。デモを用意している時間がなければ、実際に業務で使っているものに対して、テストコードの例を書いてみてもいいかもしれません。

テストコードは最初は、正直、精度も良くなく、メンテやレビューも大変です。しかし、研究では3~4回目で精度が良くなるという結果もあったりするので、そういったことからも経験を積めば、絶対的に楽になってきます。

僕自身がこのようなことをやった時には、linterを導入するなどの意見も上がってきました。実際にそれについてもvscodeのクローズドな拡張機能を作るなどして規約に則りつつ、簡単にかけるようにしていきました。

# さいごに
フィードバックの後は、それに向けた修正をするだけです。

「テスト自動化」の一歩手前の部分の導入を考えている人に向けて、まず社内でできることや保守運用の部分での「テストコードのルールづくり」について書いてみました。自分自身もこれを作ることで、QAに対する興味や自分のサービスをさらに良くする欲に駆られました（笑）

皆さんで良いサービスを作るためにテスト自動化やテストコードの導入などをしてみましょう！！