【社内勉強会】「10分ちょっとでわかる！初めての自動テスト」

# はじめに
こんにちは！
今年の4月に新卒で入社しました。[AXLBIT株式会社](https://axlbit.com/)デプロイ＆QA部の[@ax-ikezawa](https://qiita.com/ax-ikezawa)です。

今回は, 2024年6月7日,　及び7月5日に行われた社内勉強会で発表した内容を備忘録もかねて報告させていただきます。

今回のテーマは「10分でわかる○○」で, 自分と同じ新卒6人が登壇し発表させていただきました。良ければ下記のリンクから同期の記事もご覧ください！

https://qiita.com/ax-shitaya/items/adf9a0a7f5cefcfdaafb

https://qiita.com/ax-asada/items/cdad33ba4740de089096

https://qiita.com/ax-shinohara/items/ed05c26b4e53565e270d

この記事では, 「初めての自動テスト」の書籍の内容を踏まえつつ

 > 1. 各テストについて
 > 2. テストのピラミッド
 > 3. TDD
 
 という流れでご説明いたします。
 
 実際に細かい例題を用いて各テストを作る, という内容は今回省きます。興味がある方は今回参考にさせていただいた書籍「初めての自動テスト」をお手に取ってみていただけると幸いです。

 [初めての自動テスト](https://www.oreilly.co.jp/books/9784873118161/)

 # 各テストについて
 テストには **ユニットテスト**, **結合テスト**, **UIテスト**の3種類が存在します。
 それぞれのテストがどんな役割を持っているのか, どのように書けばいいのかを見ていきましょう。

 ## ユニットテスト
 ユニットテストとは, ロジック, 計算, 処理を一つ一つ確認するテストのことです。
 
 メリットには超高速でレスポンスを得られる点と様々なことを確認することができる点が挙げられ, デメリットは結合部分に弱い点が挙げられます。

 ユニットテストを書くときに考慮すべきこととして, 以下のものが存在します。
 
**ハッピーパス**　全てが正しく動いたと仮定して, 理想的な環境でメソッドはどう動作するか？
**特殊ケース**　特に注意を払うべき特殊な条件やエッジケースはあるか？
**例外**　どんな条件や例外が起きた時にこのメソッドはエラーを起こしうるか？
**プログラムのロジックと流れ**　プログラムのすべてのパス, ロジックの流れ, 条件分岐は適切に動いているか？
**その他何でも**　メソッドが正しく動いている自信を持つには他にどんなテストが必要か？

 ユニットテストの対象は　**壊れる可能性のあるもの全て**！
 メソッドが正しく動いている自信を持つために積極的に書いていきましょう。

## 結合テスト
結合テストとは, アプリケーションを動かしているサービスをテストするものです。
(書籍では「統合テスト」と表記されていますが, やや定義が曖昧なためここでは「結合テスト」と表させていただきます。)

メリットには以下のようなものが挙げられます。
・HTMLのないサービス(APIでの提供等)のテストを行える
・UIテストでもユニットテストでも見つからない中間層の不具合を発見できる
・堅牢性と機動性のバランスの取れたテスト
・Webのレイヤでのテストが行える

対して, デメリットは エラーが発生した際の原因特定が難しい, つまり**詳細さに欠ける** という点が挙げられます。

結合テストはUIの存在しないサービス(例：API)にも使用できます。その際URLを使用することでテストを行いますが, なぜそうなるのか, テストしやすいWebサービスを設計するにはどうしたらよいかは割愛しますので興味がある方は書籍をご覧ください。

## UIテスト
UIテストとは, 実際の画面を操作して動作確認を行うテストのことです。

メリットにはエンドツーエンドで動くため, ユーザと同じ視点での確認が行える点が挙げられ, デメリットはレスポンスが遅い点, 開発が高コストな点, 壊れやすい点が挙げられます。

UIテストで使うものとして, HTMLとCSSの二つが挙げられますが, これらはそれぞれ対象の存在の有無の確認と要素, 実データ等の取得という点で用途が分かれています。

# テストのピラミッド
上記で挙げた各テストの組み立て方で意識することとしてテストのピラミッド, というものが存在します。
これは作成するテストの個数の割合を示しており, できる限りユニットテストで確認を行い, ユニットテストで確認できない部分を結合テストで, それでも確認できない部分, 動作保証を行う部分をUIテストで記述する, という指標です。

UIテスト・結合テストはその性質上すべてのテストをカバーできてしまうように感じます(そしてそれはほぼ正しいです)が, すべてのテストをUIテストで行うとレスポンスが遅いために実施時間が莫大なものとなってしまい, 本末転倒になってしまいます。
また, UIテスト自体の改修も大変なため, その点でも開発コストが膨れ上がってしまうことになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776498/4092796c-91b4-4c75-cffa-4b7b62354337.png)

# TDD
TDD(テスト駆動開発)とはテストファーストとも呼ばれる手法で, テストを先に書き, そのテストを成功させるために設計・開発を行う手法です。

TDDの手順は以下のようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776498/51f10d21-89e1-05e1-676a-77ee14cff0cc.png)

3つ目のリファクタリングは特に重要であり, これを忘れてしまうとTDDの効果がなくなってしまい開発の精度を下げることにつながってしまいます。

TDDのメリットには以下のようなものが挙げられます。
・**オーバーエンジニアリングを防ぐ**
　テストを書いて必要性を示すまでコードの追加を行うことができない
　YAGNI（You Ain’t Gonna Need It：必要になるま では機能を追加しない）の原則
・**コードの設計が改善され, しっかりとテストされたコードになりやすい**
　作成した機能に対してテストが1:1対応している
　リファクタリングも必要なため保守もしやすい
・**複雑な内容を扱いやすい**
　１度に１つのことに集中できるため, ストレスの魔物を脇に避けておくことができる
　問題の単純化を行うことができる
・**単純に楽しい**
　いったんテストファーストの習慣が身につくと自然なリズムで作業を進めることができる
　小さな満足感をすぐに得られる
　作業が進んでいることが分かりやすく, 常に動作しているシステムを手元における

# おわりに
今回, 自動テストを作るに必要な基礎知識や手法について紹介しました。
これをもとに, テストのピラミッドを念頭に置きつつ良いテストを作っていきましょう。
ここまでご覧いただきありがとうございました。良いテストライフを！