🕌

【書評】「ソフトウェア品質を高める開発者テスト」を読んでテストの考えを改める

に公開

📚 この本を要約するとどんな本?

コストが増加しない・人員を増員しないという状況でも上流品質を上げる活動を提言しておりテストに対する考え方を経験を踏まえて紹介している本

本書の目的

  • Shift Leftすること
  • 楽をすること

【特に心に刺さるテーマ】

ソフトウェア上流品質を上げまくってバグだらけ・死ぬほど働くのをやめませんか?

https://amzn.asia/d/fRat38b


📚 各章ごとの印象に残ったところを教えて!

第1章

  • 従来の品質モデルとShiftLeftモデル(ピークを左に持ってくる)
  • 品質の向上活動を設計コーディングフェーズに持っていく活動
    本書では、コストが増加しない・人員を増員しないという状況でも上流品質を上げる活動を提言します。じゃなければみなさんやらないですよね?

第2章

品質向上=システムテストをちゃんとやる

  • 要求仕様の明確化
  • クラスや関数構造をシンプルに保つ
  • 単体・統合テストの実行
  • レビューの実施

早期のコードインスペクション・レビュー・繰り返し型開発、周期的構築などに重点をおくと欠陥摘出曲線は開発の初期(左側)に移動する

理論的に証明されている
→上流テストをしない=出荷後のバグが発生する

上流でテストをしないと、致命的な市場バグが発生し、開発コストが余計かかる。

第3章

単体テスト(まず抑える)

  • 境界値テスト
    • プログラムで境界と呼ばれる場所には常にバグが潜んでいるので詳しくテストする必要がある
  • 状態遷移テスト
  • 状態をモデル化しテストを行う手法
  • 状態遷移にまつわるエラー処理や例外処理はたくさんある
  • 組み合わせテスト
    • 開発をスタートする前に単体テストは下記のどちらにあたるのか明確にする

コードに対する確からしさを確認するテスト

  • Unitテスト
    • 関数の網羅率を計測しロジックの確からしさを確認するホワイトボックステスト
    • 観点
      • プログラムを実行する中で、システム上異常な振る舞いを行わない(ヌルポ)
      • 入力値とそれに対応する期待値を出力すること
      • 全ての分岐が正しく処理されること
  • 単機能に対するテスト
    • URLに遷移する
      機能単体の単体テストでの組み合わせのバグ検出確度はコードベースの単体テストよりかなり低い

第4章

入力値のパターンを100%網羅するようにし、それに対する期待処理が正しいかチェックすること

  • テスト駆動開発(TDD)
    • 実際のソースコードを書き始める前にテストケースを書く
    • 全てのテストコードは自動化する
    • バグはすぐに修正する
    • プロのテスト担当者を入れる

赤:失敗するテストを書く
緑:テストに通るような最小限のコードを書く
リファクタリング

  • Googleのコード網羅率の内部ガイドライン
    • 網羅率60%:許容範囲
    • 網羅率75%:推奨
    • 網羅率90%:模範的

第5章

  • コードの複雑度
    • 複雑度が高い:if・switch文がたくさんある
    • 複雑度が低い:if・switch文が少ない
  • 疲弊を招く一例としては、市場で出たバグの再発防止の8割は
    • レビューをしっかりしましょう
    • テストケースを追加しましょう
  • 改善とは、今ある仕事を効率的にし(残業時間を減らし)、かつ品質を上げることです。
    →今ある仕事も減らさず、さらにタスクを追加するというのはソフトウェア開発では改善とは言わない
  • 論文的にはソフトウェアのバグはソースコードファイルの10%~20%から発生
    • 直近の変更回数に重みをつけ、過去に変更されたファイルはそれほど重みをつけない
    • →直近の変更回数とファイル行数が長いものから単体テストを行なっていけば良い
  • ブラックボックステスト
    • 要求仕様によって定義された入力・出力値を使用通りにシステムもしくはコンポーネントが振る舞うかを確認するテスト
  • ホワイトボックステスト
    • 要求仕様によって定義された入力・出力値を使用通りにシステムもしくはコンポーネントが振る舞うかをコード網羅によって確認するテスト
    • 欠陥なく100%網羅されていればテスト成功とする
    • もし網羅が不足している場合には、何らかの欠陥もしくは要求仕様の不備が認められる

第6章

  • コード網羅をして、単機能のテストをするのは開発者の責務
  • 機能単位の単体テスト手法の基本
    • 単機能境界値
    • 組み合わせ
      • 一番コストのかかる方法
      • デジションテーブル
      • All-pair
  • バグの発見をシステムテストに依存している組織はたいてい、そのシステムテスト部分を協力会社に依存しています。
    協力会社もテストケースが増えれば、お金が儲かるので。
    「そうですね。組み合わせテストを増やした方がいいと思います」と言ったりします
    →組み合わせが足らないからバグがでたと思い込むのは危険です。

第7章

  • リファクタリング
    • 複雑度を下げるリファクタリング
      • 複雑度が高い関数が多ければ多いほど、労働時間は増加する
      • →残業を減らしたきゃ、複雑度を下げるしかない
    • 出口を一つにするリファクタリング
      • 関数の出口を一箇所、もしくは二箇所にすること
      • 二箇所の場合は必ず、入り口でのパラメータのエラーチェックのみで、絶対に関数の真ん中でreturnをしないようにする
    • MVC分離のリファクタリング
    • ファイルのコードを短くするリファクタリング

第8章

  • レビューとは基本的に他人の書いたものを指摘するのではなく、本人が気づくことに重点を置くもの
    →他人が書いたコードなんて一瞬で理解するのは無理なので問いかけ形式で本人に気づきを持たせる
  • なるべくコードレビューの前に機械が検出できるバグは検出しておいて、人は本当に最小限のことしかやらない仕組みにしておく
    →単体テストが失敗しているのにレビューする意味はない
  • バグを入れないようにする仕組みではなく、入れてもすぐに発見できる仕組みを入れることが重要

第9章

  • APIに入力パラメータがある場合は、そのパラメータに対して境界値テストをして、できればそのAPIを様々な形で叩き、状態遷移まで網羅できれば完璧と考える。
  • システムテスト自体の組み合わせテストは、対コスト面で全く無意味です。
    しかしAPIテスト(統合テスト)ならば多少なりとも組み合わせテストをやることは許容できます。

第10章

  • テストの自動化では、どんな自動化でもメインテナンスコストを最小限に抑えることが重要

第11章

  • 探索的テストの説明
    • スキルのあるテスト担当者が責任を持ってテストケースを書かずにテストの学習とテスト実行を高速に行う手法
  • 探索的テストが実施できる条件
    • コード網羅が概ね80%以上である
    • 網羅基準が分岐網羅である
    • アーキテクチャがMVC分離されている
    • 各関数のMcCabe数が20以下であり、クラスメンバー関数の数が10以下である
    • 全ての要求仕様がレビューされている
    • Race Condition(競合)のバグに対して十分対策がされている

第12章

  • 単体テストで多くのバグを見つけることが重要

第13章

  • 要求仕様
    • 完全である
    • 正当である
    • 実現可能である
    • 必要である
    • 優先順位がついている
    • あいまいさがない
    • テスト可能である

第14章

  • 小規模テスト
    • 一つのクラスごとにアプリの動作を検証する単体テスト
  • 中規模テスト
    • モジュール内のスタックレベルでのインタラクション、または関連するモジュール間のインタラクションを検証する統合テスト
  • 大規模テスト
    • アプリの複数のモジュールにまたがってユーザーが経験する過程を検証するエンドツーエンドテスト
  • 小規模〜大規模テストへピラミッドの段階が上がるにつれて、各テストの再現性は向上するが実行時間と保守およびデバッグの労力が増大する
  • 統合テストより単体テストを増やし、E2Eより統合テストを増やす必要がある。
    一般的に**小規模70%・中規模20%・大規模10%**の割合がおすすめ

まとめ

上流品質担保の手法

  • アジャイルでの要求変更が頻発する中での高速開発
  • CI/CDのツールと手法による高速のデリバリ
  • Hotspotを利用した効率的な単体テスト

📚 この本を読んで実生活に活かしたいことを教えて!

テストへの考え方

  • 疲弊を招く一例としては、市場で出たバグの再発防止の8割は

    • レビューをしっかりしましょう
    • テストケースを追加しましょう
  • 改善とは、今ある仕事を効率的にし(残業時間を減らし)、かつ品質を上げることです。
    →現在この思考で再発防止策を考え、提出していたので、どうにか他の対応ができないか考える

  • リグレッションテストシナリオの押さえどこ
    →どんな自動化でもメインテナンスコストを最小限に抑えることが重要

これから単体テストを書く実装が増えるので下記観点を意識

  • 論文的にはソフトウェアのバグはソースコードファイルの10%~20%から発生
    • 直近の変更回数に重みをつけ、過去に変更されたファイルはそれほど重みをつけない
    • →直近の変更回数とファイル行数が長いものから単体テストを行なっていけば良い
  • バグを入れないようにする仕組みではなく、入れてもすぐに発見できる仕組みを入れることが重要

レビュー観点

下記観点はレビュー時に全く持っていなかった。時間をかけてコードを読みレビューすることが大事だと思っていたが気付かせるという観点であれば、楽&得意領域かもしれない。


終わりに

最近テストに関わることが多く非常に参考になりました。
特に改善案を話す際は「レビューをしっかりしましょう」という結論になりがちなので、どうしたら改善できるかを意識して怠惰に働いていこうと思います。

Discussion