Tabelog Tech Blog

食べログの開発者による技術ブログです

食べログAndroidアプリの自動テスト戦略

こんにちは。食べログでAndroidアプリのテックリードをしているsadaです。
今回は食べログAndroidアプリの自動テスト戦略についてご紹介したいと思います。

目次

そもそもテストコードはなぜ必要なのか

まず自動テスト戦略のお話をする前に、テストコードがなぜ必要なのかについて考えてみましょう。
品質向上や工数削減という話はよく聞きます。
もちろん自動テストにより、ある程度の効果は見込めますが、やってみて思ったより効果が出ないと感じたことはないでしょうか?

例えば、工数削減を目的に自動テストを始めた時に、テストコードを作りはじめるとその作成・保守といったコストがかかります。確かに工数削減の効果が出ている部分があっても、期待していたより効果が出てないと感じてしまうことはよくあるかと思います。
単純に工数削減を目的とするならもっと違ったアプローチがあるのではないか、と考えることもあるかもしれません。

では、テストコードはなんのために書くのでしょうか?

書籍『Clean Architecture 達人に学ぶソフトウェアの構造と設計』には以下のような記述があります。

ソフトウェアは「ソフト」になるように考案されたものだ。マシンの振る舞いを簡単に変更する手段になることを目的としたものである。マシンの振る舞いを簡単に変更したくない時には、それを「ハード」ウェアと呼んだ。
上記の目的を達成するには、ソフトウェアはソフトでなければいけない。つまり簡単に変更できなければいけない。1

要はソフトウェアは変化に素早く対応できるべきだということですが、そのためには正しいか間違っているかを素早く検知する必要があります。
しかし、動作確認をいちいち手動で確認していたら、時間がかかって仕方ありません。
だからこそ、テストコードによる自動テストが必要になるのです。

テストコードにおいて大事なこと

私はテストコードにおいて以下の3つの観点が大事だと考えています。

  • 自動テストの信頼性
  • できるだけ早い段階で検出する
  • 継続的な保守

以下、3つの観点をもう少し詳しく説明していきます。

自動テストの信頼性

自動テストの信頼性が高いはどういったことでしょうか?
単純にテストが通ったら、バグがないというだけではありません。
信頼性の高いテストの結果が、成功していればリリースできる、失敗していればコードの修正が必要というように、次に行うべきことを即座に判断できます。

また、自動テストの信頼性の高さが重要であることは、書籍『LeanとDepOpsの科学』にも記述されています。

「テスト自動化」は継続デリバリの支柱の1つであり、その関連プラクティスのうち、我々の分析でITパフォーマンスの予測尺度となりうることが判明したのは次の2つである。2

・信頼性の高い自動テストの実施
・開発者が主体となった承認テストの作成・管理、および承認テストの容易な複製・修正

しかし、信頼性の高いテストを作るにはどうすればよいでしょうか?

信頼性を下げる要因は色々あります。よくあるのが、誤検知や見逃しと言ったアンチパターンです。

誤検知は、実際には問題ないにもかかわらず、テストが失敗している場合のことで、不安定なテスト(flaky test)や脆いテスト(fragile test)と言われるものです。
これらを改善するには、どこまでテストダブルを利用するか、どこまで検証するかなどの判断が必要になるので、テストコードを書くスキルが求められます。 また、最初に良いテストコードを書いて、信頼性の高い状態だったとしても、それだけでは維持できず信頼性が下がっていってしまいます。
そのため、特に大規模な人数のチームにおいての導入時には、テストを書く文化を根付かせ、チーム全体でスキルアップしていくことが大事です。

また、見逃しについては、テスト不足・カバレッジ不足などが原因となります。カバレッジについては、ツールが充実していますので、割と改善しやすい部分になります。しかし、テスト不足の解消にはドメイン知識・仕様把握が必要になります。
テスト不足なのにテストが成功してしまっているということはプロダクトコードが不足している状態なので、なかなか難しい問題です。
これはテストコードに閉じた話ではありませんが、しっかりと仕様を把握し、プロダクトコードとテストコードの双方にしっかりと反映していくことが大事です(当然のことではありますが)。

できるだけ早い段階で検出する

こちらはAndroid公式ドキュメントの「テスト戦略」のページの冒頭に記載されています。

Catches issues as early as possible.3
(問題をできるだけ早い段階で検出します。)

これはできるだけ早いタイミングで適切なフィードバックを受けることで、開発生産性を最大化できるということです。
例えば、単体テストで検出できればほんの数分で修正できますが、手動テストだとアプリが完全に動かせる状態まで実装する必要もありますので、数時間〜数日かかることもあるかもしれません。
これはたとえ、E2Eテストで自動化できていたとしても、CIの実行サイクルなどによってはフィードバックが得られるのに数日かかってしまうこともあるかもしれません。
ですので、開発生産性を最大化にするためには、自動テストがあればいいということでもなく、最適なタイミングでのフィードバックが必要ということになります。

適切なフィードバックを設計する上で、重要なことはテストピラミッドと言われる比率とテストサイズという分類になります。

テストピラミッド

テストピラミッドとはコストと忠実度(どれだけ本番環境に近いかという度合い)が高く、実行速度と決定性(毎回同じように安定して動くかという度合い)が低いテストほどケース数を減らすべきという、テストケース数の比率を視覚化したものです。
このピラミッド型の比率が、自動テストの信頼性を中長期的に保つ最適なバランスと言われています。

次にテストサイズですが、これはテストを規模により分類した基準です。
以前はユニットテストやインテグレーションテスト、E2Eテストといったような「テストスコープ」と言われる分類で考えられていたのですが、ユニットテストというものがどういったものを示すのかというと、人によってまちまちで、分類が難しいという問題がありました。
例えば、テスト対象クラスの依存クラスをテストダブルを利用するのか、本物を使うのかという点でもテストダブルを利用するのがユニットテストという人もいれば、両方ともユニットテストだができるだけ本物を使った方が良いと答える人もいます。これは所謂ユニットテストにおける流派の違い(デトロイト学派とロンドン学派)だったりします。
そこで、登場したのが「テストサイズ」という分類で、これは書籍『Googleのソフトウェアエンジニアリング』で以下のように紹介されています。

我々は、あらゆるテストケースについて、2つの別個の次元があるという結論に達した。それは、規模(size)と範囲(scope)だ。規模は、テストケースの実行に必要なリソースを指し、メモリー、プロセス、時間等だ。範囲は、検証している特定のコードパスを指す。4

そしてこの規模の大小によって Small / Medium / Large という分類をします。
それぞれのサイズについて具体的に説明すると以下のようになります。

サイズ 説明
Small 単一プロセス内で実行される
Medium 単一マシン上で実行される
Large 任意の好きな場所で実行される
(Enormous) (Googleではこの区分も存在するらしいですが本稿では割愛します)

これをAndroidにおけるテストに当てはめると、例えば以下のようになります。

Small Medium Large
ネットワーク NG localhost OK
ローカルデータベース NG OK OK
Android OS NG OK OK
マルチスレッド NG OK OK
外部システム NG NG OK

NG : 使用しない or テストダブル等を利用する
OK : 基本実装のまま動かす(一部テストダブルを利用することもある)

例えば、テストにCoroutinesが関わる場合、SmallならTestDispatcherを利用して、Mediumなら実装のまま動かすという形になります。
ただし、一口にMediumといっても内部的には段階があり、Mediumテストでも実行速度・決定性を重視して、一部テストダブル(例えば オンメモリDBやRobolectricなど )を利用するということはありえます。

このようなテストサイズという分類とテストピラミッドの比率を考えることで、最適なフィードバックループを設計できます。

Android公式ドキュメントのテスト戦略のページに「スケーラブルなテスト戦略」というセクションがあり、ここに例として5つのレイヤーでカテゴライズしたピラミッドがあり、その説明に以下の記載があります。

This categorization takes into account fidelity, time, scope and level of isolation. 5
(この分類では、忠実度、時間、範囲、分離レベルが考慮されます。)
スケーラブルなピラミッド

忠実度はピラミッドの上であるほど高く、時間は下に行くほど速くなります。
また、範囲はテストスコープ、分離レベルはテストサイズを指します。

こちらはあくまで一例でチームによってレイヤの定義が異なることもあるかとは思いますが、こちらを参考に以下の内容を検討することで、最適なフィードバックループを設計できるかと思います。

  1. テストカテゴリを定義する
  2. 各テスト対象がどのカテゴリになるか検討する
    • ここではなるべくピラミッドの最下層になるよう検討する
  3. ワークフローのどのタイミングで各テストを実行するか設計する
    • 実行のトリガーはチームの生産性等も加味して検討する

継続的な保守

書籍『Googleのソフトウェアエンジニアリング』に以下の記載があります。

理想のテストとは、変化しないテストである。つまり、テスト対象システムの要求が変化しない限り、書かれた後は二度と変更の必要がないテストだ。6

理想としてはまさにその通りですが、実際にはせっかく整えたテストも時間経過で劣化していきます。
スキルは人それぞれですし、プロダクトが変化するなら、当然テストコードが追加・修正されたりすることもあります。

また、同書に「信頼不能テストのコストが高い」というケーススタディが紹介されていますが、その中の一文に以下のような記載があります。

テストへの信頼の喪失が起こると、エンジニアはテストの失敗に反応することをやめ、テストスイートの提供する価値が全部削がれてしまう。我々の経験が示唆するのは、信頼不能性が1%に接近すると、テストは価値を失い始めるということだ。7

テストが定期的に失敗してしまうと、「またか、とりあえずリトライしてみるか」というようにフィードバックを得るのに時間がかかってしまったり、「どうせいつものだから見なくてもいいや」というように、もはやエラーを見ることをやめてしまうようなことになってしまうかもしれません。

このような事態に陥らないように、信頼性が高く、できるだけ早い段階での検出が可能なテストを中長期的に保つために継続的な保守をする必要があります。

これを怠ると、せっかく作り上げたテストコードが水の泡になりかねません。

食べログAndroidアプリの自動テスト戦略

ここまでですでにだいぶ長くなりましたが、テストコードの必要性と、テストコードにおいて大事なことを説明してきました。
理想形はだいぶイメージがついたかと思います。

ただし、最初から理想通りにテストコードが書けるかというとそんなことはありません。

理想に近づけていくためには、しっかりと戦略を練ることが大事です。
そこで、食べログAndroidアプリではどのような戦略を取ったかをご紹介したいと思います。

結論からいうと、一番早くフィードバックが得られるものから積み上げていく(ビルドアップ)戦略を取りました。

ピラミッドを積み上げる

この戦略は、実際のテストコードを積み上げるだけでなく、自分たちのテストコードを書くスキルや、モチベーションについても合わせて積み上げていける点が良いところです。

なぜこのような戦略を取ったのかというと、以下の3点が重要だと考え、それを実現するためにこの戦略を選択しました。

  • テストコードを書く文化を根付かせる
  • 一番欲しいフィードバックを考える
  • バランスよく積み上げられる

それでは、重要なポイントについて詳しく説明していきます。

テストコードを書く文化を根付かせる

何事においてもですが、良い文化を根付かせることは非常に重要です。
文化として根付いたものは、行うのが当然となり、継続的に行われるようになります。

食べログAndroidアプリは、私が入社した2018年8月頃にはテストコードがまったくない状態でした。テストコードを書いたことのある人も少なく、もちろんテストコードを書く文化も根付いていませんでした。

その状態から既存のプロダクトにテストコードを書く文化を根付かせるのに大事だと思った点は以下の通りです。

  • テストコードに関心を持ち、テストコードを書くことに慣れる
  • テストコードを書くことで得られるフィードバックを体感する

まずは「テストコードに関心を持ち、テストコードを書くことに慣れる」という点です。
人は知らないことに対しては恐怖や抵抗感など否定的な感情を持つことが多いです。
(もちろん反対に知らないことを知るという喜びを感じる人もいたりはしますが、一般的にはという意味です。)

そういったネガティブな感情を持ったままだと、テストコードを書く文化を根付かせるなんていうのは、なかなか難しいでしょう。そのため、まずはテストコードに関心を持ち、テストコードを書くことに慣れていくことが大事だと考えました。

ただし、それだけでは不十分で、ただ書くだけでは手間が増えただけになってしまいます。
そこで、次に「テストコードを書くことで得られるフィードバックを体感する」という点が重要になります。

フィードバックを得ることで、自分のコードを素早く評価できる体験をすれば、テストコードがあると結構便利だなと感じるでしょう。
そのためには、なるべく速い段階でのフィードバックがあると良いです。

そういった点を踏まえて、一番Smallなテストを書くことから始めました。

例えば、INPUTとOUTPUTが明確な関数があったとします。ただし、その中にはいくつかの条件分岐があったとすると、そのテストを手動で行うとしたら、かなり大変な労力になります。
そこでユニットテストを書いたとすると、簡単にその関数のテストが実施できてしまいます。境界値テストなども、コードなら簡単に書けることでしょう。
このように、ユニットテストを書くことで素早いフィードバックが得られそれを体感すると、テストコードを書くことのメリットの一端を感じることができるかと思います。

ただし、すべてのクラスでユニットテストを書きましょうとか、カバレッジをできる限り担保しましょうというのはこの時点では設定していません。
というのも、下記ブログにてご紹介していますが、当時はプロダクトコードにかなりの負債が貯まっており、ユニットテストを書きたくても書きづらい状況でした。

食べログAndroidアプリの技術的負債解消への道のり

そのためテストコードを書く対象は、ロジックが独立していて依存が少ない箇所であったり、設計の刷新が完了して集約したロジックがある箇所などに絞ることで、なるべくコスパの良いテストコードを書くようにしました。

一番欲しいフィードバックを考える

次に考えたのは「一番欲しいフィードバック」が何かという点です。

当時、テストコードがない時代でも、しっかりとした手動テストで品質を担保していました。
リリース前にはかならずリグレッションテストを行なっていましたので、最終的にリリースして良いのか・不具合があるのか、というところでのフィードバックは得られている状態ではあります。
もちろんE2Eテストで自動化した方がより早くフィードバックは得られますが、タイミングの速さで考えると、リリースフロー的にいうと長くても半日程度でした。

また、既存コードへ機能追加をする際も機能の大小にもよりますが、簡単な仕様変更なら数時間程度でアプリを起動して動作確認できます。

ところが、先ほどのセクションでお話しした設計の刷新は、画面単位での刷新を行なっていたので、View / Presentation / UseCase(Domain) / Infrastructure というようなレイヤーで実装する各種クラスを全て実装しないとアプリは基本動きません。
それらを実装するまで、早くても数日、規模の大きい画面なら1週間はかかることもあります。
その間、コードレビューぐらいのフィードバックしかない状態になってしまいます。
もちろん、一時的にDummyを用意するなどして、確認できる部分もありますが、それならテストコードを書いてしまった方が効率的です。

このように、新規にクラスを作っていく際にユニットテストを合わせて書いていくことが、一番フィードバックが得られて嬉しいタイミングでした。

また、テストコードを書くことによって、そのクラスの設計の良し悪しを検証できる側面もあります。
テストコードが書き辛いクラスは、依存関係であったり、メソッドの粒度であったり、どこかに問題を抱えている可能性が高いです。
そういった面のフィードバックもあるので、設計の刷新を進める際にユニットテスト書くのは大変効果的でした。

バランスよく積み上げられる

テストピラミッドのお話しをさせていただきましたが、最初から完璧な比率で自動テストを作るのはかなり難しいです。
テスト比率のアンチパターンとしてよくアイスクリームコーンが挙げられたりします。
このバランスだと中長期的に保守していくのが大変になってきてしまいます。
そのため、ピラミッドの比率になるようテストコードもリファクタリングしていく必要がでてきます。

アイスクリームコーンからピラミッドへ

重要なのはこのテストピラミッドに対して、どのようなアプローチで向かっていくかということです。

そこに対して、私たちはSmallなテストから積み上げていくアプローチにしました。
最初にSmallテストをたくさん作ることで、Smallテストでは作りにくかったテストや、できていないテストといった課題が見えてくるので、そこを補う形でMediumテストを作っていくことができます。

例えば、Viewに表示するデータを生成するロジックはユニットテストで担保できますが、実際にViewに差分があるかなどは難しいです。こういった部分をMediumテストで作っていくと、単純なクラス間の結合テスト的なものだけでなく、担保できる部分が増えていくので、テストコードの信頼性が高まっていくと考えられます。

実際進めてどうなったか

まずはSmallテスト主軸に

現状のSmallテストの充実具合を以下の表にまとめました。

テスト対象クラス数 テストクラス数 割合
Presentation 117 71 60.68%
UseCase(Domain) 138 125 90.58%
Infrastructure 78 71 91.03%

Smallテストといっても、すべてのクラスにテストコードを書いているわけではなく、ある程度ロジックが集約するところを重点的にテストコードを書いています。
そのため、上記表ではロジックが集約する各種レイヤー毎にまとめました。

Presentationについては、Viewにバインドするためのデータクラスを生成するようなロジックや、画面遷移・データ取得・計測などを実行するのに必要なパラメータを生成するようなロジックが集約されたクラスをテスト対象としています。
そのため、APIで取得したデータをそのまま表示するような簡単な画面ですとテストを省略することもあるため、テストクラス数がやや少なめです。

UseCase(Domain)については、状態チェックや複数のデータを組み合わせて取得するロジックなどが集約されているため、基本的にはテストを書いています。
ただし、Presentaionと同様に取得したデータをただ返すだけのような場合には、テストコードを省略することもあるため、9割程度になっています。

そしてInfrastructureについては、主にキャッシュロジックなどが実装されており、こちらはUIからはわかりにくい処理のためほぼテストコードを書いています。
そのため、9割程度はテストクラスが用意されています。

このように重要度を考えて多少テストコードを省略することを許容しつつですが、基本的にはテストコードを書くことを推奨するという形でテストコードを書き始めた結果、徐々にテストコードを書くことに慣れていき、今では全体的にテストコードを書くのが一般的になってきました。
まだまだな部分もありますが、テストコードを書く文化が根付いてきているのが、数値にも出ていると思います。

また、Smallテストを書くことにより、早めのフィードバックを得ることで良かった点をいくつか挙げておきます。

  • テストコードを書くことで、結合前に不具合に気づき、結合時の不具合を減らすことができた
  • テストコードが書き辛いことから設計上の問題に気づき、適切にロジックを集約できた
  • テストコードがかなり多くなってしまったことでクラスの責務の多さに気づき、適切に分割できた

「一番欲しいフィードバックを考える」というセクションで述べたように、テストコードを書くことで設計の問題に気づくことができたり、結合前に不具合に気づくことができたりと、テストコードを書くことのメリットを実感できました。

次にMediumテストでカバー範囲を広げる

Smallテストが増えてきたので、次にSmallテストではカバーできていない部分のテストコードを書きました。
具体的には、以下のようなテストです。

  • リグレッションテスト
  • スクリーンショットテスト

まずリグレッションテストについてですが、食べログでは週1回の定期リリースをしており、毎週金曜にコードフリーズした後に手動でのリグレッションテストを行っていました。
そのため、結合して問題があるようなケースだと、例えば月曜にマージされた機能で問題があった場合に、金曜のリリース作業中に発覚することがありました。(極端な例ではありますが)
これだとフィードバックとしてはかなり遅い状態です。

また、UIの差分についても、基本目視での確認となっていたため、チェックにも時間がかかるし、最悪見逃してしまうケースもありました。
フィードバックのタイミングについても、実装が全て終わった後の結合試験時に修正前のアプリと比較検証をして気づくといったケースが多くなっていました。

これらを改善するために、可能なものを自動テストに移行して、なるべく早い段階でフィードバックを得られるようにしました。
テスト自体はLargeテストとして作ることもできますが、APIなどの部分をテストダブルを利用してサーバーとの依存をなくすことで、テストサイズをMediumに抑えることができます。そうすることで、APIの冪等性も担保でき、かつテストコードの実行速度も速くなります。ピラミッドでいうと、決定性と実行速度を上げ、忠実度が下がる形になります。
また、テストのためのインフラ構築の必要もないため、自分たちで始めるのも比較的簡単にできます。
APIのテストダブルには、MockWebServerを利用しており、以前にチームメンバーが記事を書いていますので、よかったら参考にしてみてください。

MockWebServerを使ったAndroidアプリのUIテスト

現在では以下テストケースをMediumテストとして自動化し、Nightly(平日0時)+リリース前で実行するようにしています。

  • 手動で行っていたリグレッションテストの内、 206/292(70.55%) のテストケースを作成
  • 66パターンのスクリーンショットテストを作成

これにより、今まで手動テストではリリース前のみ行っていたリグレッションテストが、一部を除いて開発ブランチで毎日実行されるようになり、最長4日後に検知されていたものが翌日には検知できるようになりました。

また上記のような定期実行以外に、設計の刷新時のように画面単位でを大きく作り直す際にスクリーンショットテストや計測などの処理をMediumテストで自動化することで、今まで手動で確認していたようなテスト項目も簡単にチェックでき、かつ繰り返し実行も可能になったので、品質担保はもちろんのこと早い段階での検出ができることで開発効率が向上しました。

今後の展望

これまで紹介させてもらったようにテストコードを充実させてきましたが、まだまだ課題はあります。
具体的には以下のような点が挙げられます。

  • Largeテストを作り、手動テストを減らしていく
  • フィードバックを早める
  • テストの信頼性をより高める

Largeテストを作り、手動テストを減らしていく

Mediumテストを作ることで手動テストはだいぶ減りましたが、やはりまだ残っていますので、Largeテストを作り、手動テストを減らしていくことも検討しています。
これにより、自動テストの結果を見るだけで、リリースできるかどうかのフィードバックを可能にし、より素早い判断ができるようにしていきたいと考えています。

フィードバックを早める

例えば、新規のクラスを作る際に、Smallテストを書くタイミングは、クラスの実装がある程度終わってから行うことが多いのが現状です。
クラスの設計・実装初期の段階でテストコードを書くと、実装中にもフィードバックが得られるので、より良い設計が可能になります。
このように、フィードバックのタイミングをもっと早めていくというのも重要になります。

また、自動テストの実行時間もより短くなるように改善するなどして、CIからのフィードバックの時間やタイミングをより早いものにしていきたいと考えています。
例えば、Nightlyで実行しているテストも実行時間が短くなれば、Pull Requestが作成された時やマージされた時に実行することも可能になります。

こうして、フィードバックサイクルをより早めていくことで、変化により早く対応していくことが可能になると考えています。

テストの信頼性をより高める

現状では、テストコード自体にもまだまだ改善できるポイントがあります。

例えば、上述したようにテストを書くタイミングがクラス実装後のため、どうしても内部構造に依存しがちな脆いテストを書いてしまうことがあります。
これではテストの信頼性が下がってしまいます。

また、コードカバレッジについても、もう少しわかりやすい可視化をしたいと考えています。
単純なカバレッジを出すのではなく、カバレッジの差分を出すことでテストができていないということに気づけるようにしたいと思います。

まとめ

今回の記事ではテストコードの重要性について説明させていただいた後に、実際に食べログAndroidアプリでどのようなアプローチを取ってきたのかをご紹介しました。

アプローチ方法は、プロダクトや組織の状況によって、様々になります。
大事なのは、自動テストからどのようなフィードバック得たいのかということを考え、自分たちの状況に照らし合わせて、選択していくことだと思います。

最後に、書籍『LeanとDepOpsの科学』にこのような記述があります。

信頼度の高いテストスイートを作り上げる継続的な努力と投資は価値がある。8

これからもテストコードを良くしていけるように頑張ります。


  1. 「Clean Architecture 達人に学ぶソフトウェアの構造と設計」
    Robert C.Martin (著), 角 征典 (翻訳), 高木 正弘 (翻訳)
    第1部 第2章 「アーキテクチャ」より引用
  2. 「LeanとDevOpsの科学 テクノロジーの戦略的活用が組織変革を加速する」
    Nicole Forsgren Ph.D. (著), Jez Humble (著), Gene Kim (著), 武舎広幸 (翻訳), 武舎るみ (翻訳)
    第1部 第4章「4.4.2 テスト自動化」より引用
  3. Android Developers 「Testing strategies」より引用
  4. 「Googleのソフトウェアエンジニアリング 持続可能なプログラミングを支える技術、文化、プロセス」
    竹辺 靖昭 (監修), Titus Winters (編集), Tom Manshreck (編集), Hyrum Wright (編集), 久富木 隆一 (翻訳)
    「11章 テスト概観 11.2 テストスイートを設計する」より引用
  5. Android Developers: Testing strategies 「A scalable testing strategy」より引用
  6. 「Googleのソフトウェアエンジニアリング 持続可能なプログラミングを支える技術、文化、プロセス」
    竹辺 靖昭 (監修), Titus Winters (編集), Tom Manshreck (編集), Hyrum Wright (編集), 久富木 隆一 (翻訳)
    「12章 ユニットテスト 12.2.1 変化しないテストを目指す」より引用
  7. 「Googleのソフトウェアエンジニアリング 持続可能なプログラミングを支える技術、文化、プロセス」
    竹辺 靖昭 (監修), Titus Winters (編集), Tom Manshreck (編集), Hyrum Wright (編集), 久富木 隆一 (翻訳)
    「11章 テスト概観 11.2 テストスイートを設計する」より引用
  8. 「LeanとDevOpsの科学 テクノロジーの戦略的活用が組織変革を加速する」
    Nicole Forsgren Ph.D. (著), Jez Humble (著), Gene Kim (著), 武舎広幸 (翻訳), 武舎るみ (翻訳)
    第1部 第4章「4.4.2 テスト自動化」より引用