Googleのソフトウェアエンジニアリング(品質に関する部分)を読んだメモ・感想/11章 テスト概観
こんにちは。kubopです。
QA活動をしていく中で、Googleのソフトウェアエンジニアリングの11章〜14章を読みました。読書メモを書いていたのですが、忘れないよう、思い出しながら感想や、まとめを書きます。
※ まだまだ理解しきれていない部分があるため、解釈が異なる点があるかもしれません。
今回は11章、テスト概観について
自動テストとは
自動テストは、バグを見つけるのと同時に「変化」を可能とする能力を備えておくために必要。
自動テストの定義
最も単純な自動テストの定義とは、以下のようなもの。
1. テストしている単一の挙動。呼び出しメソッド or API
2. 特定の入力でAPIに渡す何らかの値
3. 観察できる出力か、挙動
4. 単一の分離されたプロセスのような制御下の環境
以上のような単純なテストを纏めたものをテストスイートと呼ぶ。
テストスイートの作成と保守には大変なコストがかかる。コードが大きくなるほどテストスイートは比例して大きくなるらしい。
適切ではないテストスイートは、テストスイートが無いよりも悪い。
テストは後からの付け足しはあってはならない。
何故なら品質とテスト自体が、業務遂行方法の一部であるから。
テスト自動化の形式
テストを書く
テストを実行する
テストの失敗に反応する
健全な自動テスト文化は、テストを書く作業の分担共有を促す。
そのような文化は、定期的なテスト実行も担保する。
すると、その高い信頼性を維持するため、破綻したテストの迅速な修正を重視させる。
テストが失敗したそのすぐ後に、破綻したテストを修正することを優先するチームでは、テストの信頼性を高く保つと同時に、失敗の切り分け速度を高速に保つことができる。
そして、作成した自動テストを価値が高いものにする。
コードを自動テストする利点
デバッグの減少
プロジェクト存続期間を通じて、一度書かれたテストは配当金支払いのように利益を定期的に産み続ける。
変更への信頼の増大
十分なテストを備えるチームは、プロジェクトの重要な挙動が継続的に検証されている。
そのため、変更を受け入れやすく、リファクタリングを促進する。
ドキュメンテーションの改善
ドキュメンテーションの信頼性は低いが、新しい機能が既存テストを破綻させるため、ドキュメントが陳腐化しているということのシグナルとなる。
レビューの単純化
思慮に富む設計
高速で高品質なリリース
テストスイートを設計する。
テストには2つの次元があるらしく、
以下は相関関係にあるものの、別の概念であるため注意らしい。
相関関係があるにしろ、テストサイズ大×テスト範囲小・中などという掛け合わせはあるんだろうか…?
比例するものの、議論する際には規模と範囲をわけて話す・考えるというものなのかもしれない。
規模: Size
テストケースの実行に必要なリソース。(メモリ・プロセス・時間など)
範囲: Scope
検証している特定のコードパス。(../fuga/hogehoge…)
テスト規模: Size
テストの規模は以下のサイズに分類される。
全てのテストに共通して重要なのは、密閉された状態となること。
テストは、そのテスト自身の環境の組み立て・実行・解体情報を持つべきであり、実行順序や外部環境などの前提条件はなるべく持たない方が良いらしい。
また、テストはそれ自体のテストは存在しないため、そこは手作業でのレビューが必要。
…なので、テストの信頼性をわかりやすく、かつ担保するために、テスト内での条件分岐・ループのような制御フロー文は非推奨。
複雑なテストはそれ自体がバグを孕む可能性があり、失敗原因を確定するのが難しい。
小テスト
単一プロセスで実行される。
複数制約があるものの、高速で実行されることが期待される。
中テスト
単一マシンで実行される。
複数プロセスがテスト可能であり、スレッドを使える。
大テスト
任意の好きな場所で実行される。
E2Eテストなど、システム全体のテストが行われる。
テスト範囲 : Scope
テスト範囲は、あるテストでどの量のコードが検証されるかを指す指標。
推奨とされるのは、小範囲>中範囲>大範囲のピラミッド構造。
おおよそ80%:15%:5%の比率が良いとされるらしい。
無闇にE2Eを増やすというよりも、各ロジックをしっかり検証したほうが良いのかもしれない。
小範囲
ユニットテストと呼ばれる。
個別のクラス・メソッドのような口座名義の小さな注目部分のロジックを検証する。
中範囲
インテグレーションテストと呼ばれる。
少数のコンポーネント間の相互作用を検証する。
サーバー⇄データベースなど。
大範囲
ファンクショナルテストと呼ばれる。
E2E、システムテストなどとも呼ばれる。
システムの相互作用や、単一クラス・メソッドでは表現出来ない挙動を検証する。
コードカバレッジについて
コードカバレッジは行が呼び出されたことを計測するだけ
コードカバレッジは、行のカバー率を計測するだけで、結果として何が起こったのかはわからない。
また、コードカバレッジそれ自体はテストされていないコードについて理解できるけど、システムがどれだけ適切にテストされているか。
顧客が動作することを期待するものが、全て動作するのか。
テストは安定していて、信頼できるものなのか。
については教えてくれない。
より良いテスト文化を醸成するには
オリエンテーション講習を行う
新しく入社した社員に、テストや品質についてのオリエンテーションを行う。
そうすると1-2年程でテストや品質についてあたりまえに考えるような集団が、既存集団(テスト・品質を重要視しない集団)を超えるそうな…?
テスト認定プログラム
テストプロセスを理解出来ているかを客観的に評価する。
その成熟度によってレベリングすることで、各レベルごとに改善方法を手順にまとめてステップアップさせる。
トイレテスト
テストや品質におけるTipsを、トイレの個室に貼っておく。
TotT(Testing on the Toilet)については、論文が出ているようなので、こちらも合わせて…
ただ、フルリモートの企業には代替する手段があるのかな?
自動テストの限界
自動テストは、テストのタスク全てに適しているわけではなく、
人間による判定が必要な場合が多いらしい。
例えば、検索をテストする時に、クエリに対して「期待通りの検索結果」かは人間の感性による評価が正しいし、
複雑なセキュリティ脆弱性の探索は人間のほうが得意。
探索テスト(Exploratory Testing)
自動テストでは検知出来ない挙動を、対象のアプリケーションを実際に探索し、パズルのように不具合を発見することが大事らしい。
また、そこで見つかった問題は、直ちに将来のリグレッションを防ぐために自動テストとして追加するべきらしい。
ただ、探索テストは「ランダムで無作為」なテストではないことは注意。
テスト設計を行った上で、想像的にテストをしていく、といったことが必要。
おそらく、ドメイン知識が十分にある人が行うテストと、全く知識のない人が行うテストの差。テストを事前にどのように設計しているのかを理解している場合と、それ以外の場合の差?
以下のブログが関連して面白かったため、是非読んでみてください。
結論・まとめ・思ったこと
自動テストはリファクタリングに必須。
自動テストがあると、リファクタリングをする際に非常に心強い。
特に、テストが難しい部分とか、分岐が複雑になっている場合。
数多くのステップを必要とする分岐は特に見逃しやすいし、リファクタリングする時に限って爆発するケースが…。
また、完璧だと思っていた仕様も、リファクタリングしてテストを見返していると不具合が発見されることもありそう。
テストをスケールするためには、自動化が必要。
ユーザーが選択できる分岐が多くなればなるほどに手動ではカバー不可能になる。
不具合発見 -> 修正 -> 分析 -> 自動テストケース,観点に追加 or 作成。というサイクルが出来てくると、良さそう。
健全なテストカバレッジを維持するためには、バランスの取れたテストスイートが必要。
自動テストを厚くすればするほど、リリースまでに時間がかかる。
そのため、高速で出来る小範囲のテスト・小サイズのテストをいかに基礎として作成し、中・大テストを別視点で検証出来るか(各サイズ・範囲と重複しない)が大事っぽい・・・。難しい。
例えば、メモ帳アプリであると「書く」というのは小テストで担保し、「書いたものをデータベースに保存できるか」は中テストで担保。
「各ブラウザでメモを投稿」というクロスブラウザの観点や、シナリオ、処理速度や負荷の観点を大テストで担保出来るようになるといいのかな?
テストそれ自体は人のレビューが必要。
テストのテストが存在しないので、テストはシンプルで、脳に負荷がかからないようなロジックで書かれるべきというのは凄い同意。
DRYなコードを書こうとすると、どうしても複雑になったり難しくなったりするのですが、なるべくテストに関してはシンプルに読んでわかるような実装になっているのが良いらしい。自分でも気をつけよう。
組織内のテスト文化を変えるには時間がかかる。
品質やテストについての文化は醸成にかなり時間がかかるらしい。
確かに開発をしている際は、テストを書いたりはするけど、サービス全体の品質についてはQA活動をする前にはしっかり考えていなかったな…。