Full Stack Testingに学ぶソフトウェアテストの全体像

これは、[NTT テクノクロス Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ntt-tx) シリーズ 1 の 16 日目の記事です。

こんにちは。NTT テクノクロスの際田です。普段は社内の開発プロセス効率化、テスト自動化周りの支援に携わっています。

仕事柄テスト関係の本を読んだり資料を探したりすることが多いのですが、いろいろなテスト手法が一冊にまとまってこれだけ読んだら テストのことはだいたい分かる、みたいな本がないかな～と思っていたところ、 [Full Stack Testing](https://www.thoughtworks.com/insights/books/full-stack-testing)という本を知りました。
その名のとおりソフトウェアの全てのレイヤーのテストがカバーされており、全体像を把握するのにうってつけといった感じの本なのですが、残念ながら邦訳がないようなので、 この記事では 書籍「Full Stack Testing」で説明されているものを中心に、ソフトウェアテストに求められる概念・スキル・ツールを紹介します。
(以降、書籍というのは Full Stack Testing のことを指します)

## フルスタックテストとは

ソフトウェアが複雑化・多様化するのと同様に、品質を保証するためのテストに求められるスキルや手法も増えています。
ソフトウェアの品質は、「バグがない機能」という当たり前の観点の他にも、セキュリティ、パフォーマンス、アクセシビリティなど、様々な観点からの評価が求められます。
このような観点には、それぞれ適した検証手法やツールがありますが、それらをアプリケーションの全てのレイヤー(UI/サービス/データベース)に適用し、多角的に検証を行うことで高品質なソフトウェアを生み出す活動を**フルスタックテスト**と呼んでいます。

書籍では、フルスタックテストを実践するために重要な概念として下記を述べています。

- 全てのアプリケーションレイヤーでテストすること
- シフトレフトでテストすること
- フルスタックテストを支える 10 のスキル

### 全てのアプリケーションレイヤーでテストする

多くのアプリケーションは下図に示すようにレイヤーに分かれていますが、フルスタックテストでは、それらの全てのレイヤーをテストします。
そのとき、各レイヤーに対して細かくテストをするマイクロな観点と、レイヤーにまたがってテストをするマクロな観点の両方を考慮することが重要です。
各レイヤーをテストするのに適したツールや技法はそれぞれですが、求められる観点やスキルセットは共通しています。
たとえば、機能的なテストは、UI レイヤーにも、サービスレイヤーにも、データベースにも適用することができ、また、それら全てのレイヤーにまたがった E2E テストとしても実行できます。
同様に、セキュリティや、パフォーマンステストも、アプリケーション全体に対してだけ行うのではなく、各レイヤーに対してそれぞれ適した方法で行うことができます。 (中には、ビジュアルテストやアクセシビリティテストのように、特定のレイヤーにだけ適用されるものもあります)
したがって、フルスタックテストとは、それ用の特定のスキルというわけではなく、様々なスキルを全てのレイヤーにおいて適切な粒度で活用することができる、複合的なスキルセットであると言えます。

![fste_0101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629419/72b1741b-927c-8b05-deac-9eff901e1a33.png)

(引用: Gayathri Mohan, Full Stack Testing, p.4, Figure 1-1. A representation of full stack testing)

### シフトレフトでテストする

従来のソフトウェア開発ライフサイクルの活動の順序では、要件分析、設計、開発、テストという流れになり、テストは最後に行われます。
このような場合、不具合の発覚が遅くなり、リカバリーのための時間が十分に取れないことがあります。この問題を回避するために、テストを活動の初期(左側)から実施し、早期にフィードバックを受けられるようにすることを**シフトレフト**と呼びます。

![fste_0102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629419/d809b632-1d5a-8e07-b11a-05134e6deb06.png)

(引用: Gayathri Mohan, Full Stack Testing, p.5, Figure 1-2. Shift-left testing)

### フルスタックテストを支える 10 のスキル

書籍では、複数のアプリケーションレイヤー、複数の品質観点に対してテストを行うためのスキルセットを 10 に分類し、それぞれの重要性と実践的なテスト技法・ツールについて説明しています。
書籍の中で説明されている各スキルと、そこで使われるツール群を示します。
※ 基本的に Java・Web・モバイルが主なので、それに応じた選定となっています。やや古いかな？というものもありますが、そのまま載せています。

| No  | スキル                    | ツール                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| :-- | :------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1   | 手動探索的テスト          | [Postman](https://www.postman.com), [WireMock](https://wiremock.org), [Bug Magnet](https://bugmagnet.org), [Chrome DevTools](https://developer.chrome.com/docs/devtools?hl=ja)                                                                                                                                                                                                                                                                                     |
| 2   | 自動機能テスト            | [Selenium](https://www.selenium.dev), [Cypress](https://www.cypress.io), [REST-assured](https://rest-assured.io), [JUnit](https://junit.org/junit5/), [Pact](https://pact.io), [Karate](https://github.com/karatelabs/karate)                                                                                                                                                                                                                                      |
| 3   | 継続的テスト(CI/CD)       | [Git](https://git-scm.com), [Jenkins](https://www.jenkins.io)                                                                                                                                                                                                                                                                                                                                                                                                      |
| 4   | データテスト              | [SQL](https://ja.wikipedia.org/wiki/SQL), [JDBC](https://docs.oracle.com/cd/E16338_01/java.112/b56281/overvw.htm), [Apache Kafka](https://kafka.apache.org)/[Zerocode](https://github.com/authorjapps/zerocode),[Testcontainers](https://testcontainers.com), [Deequ](https://github.com/awslabs/deequ)                                                                                                                                                            |
| 5   | ビジュアルテスト          | [BackstopJS](https://github.com/garris/BackstopJS), [Cypress](https://www.cypress.io), [Applitools Eyes](https://applitools.com/platform/eyes/), [Storybook](https://storybook.js.org)                                                                                                                                                                                                                                                                             |
| 6   | セキュリティテスト        | [OWASP Dependency-Check](https://owasp.org/www-project-dependency-check/), [OWASP ZAP](https://www.zaproxy.org), [Snyk IDE Plug-in](https://snyk.io/jp/platform/ide-plugins/), [Talisman](https://github.com/thoughtworks/talisman), [Chrome DevTools](https://developer.chrome.com/docs/devtools?hl=ja), [Postman](https://www.postman.com)                                                                                                                       |
| 7   | パフォーマンステスト      | [Apache JMeter](https://jmeter.apache.org), [Gatling](https://gatling.io), [Apache Benchmark](https://httpd.apache.org/docs/2.4/programs/ab.html), [WebPageTest](https://www.webpagetest.org), [Lighthouse](https://developer.chrome.com/docs/lighthouse/overview?hl=ja), [PageSpeed Insights](https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect), [Chrome DevTools](https://developer.chrome.com/docs/devtools?hl=ja)                                 |
| 8   | アクセシビリティテスト    | [WAVE](https://wave.webaim.org), [Lighthouse](https://developer.chrome.com/docs/lighthouse/overview?hl=ja), [Pa11y CI](https://github.com/pa11y/pa11y-ci), [Axe-core](https://github.com/dequelabs/axe-core)                                                                                                                                                                                                                                                       |
| 9   | 機能横断的要件(CFR)テスト | [Checkstyle](https://checkstyle.sourceforge.io), [PMD](https://pmd.github.io), [ESLint](https://eslint.org), [Chaos Toolkit](https://chaostoolkit.org), [ArchUnit](https://www.archunit.org), [JDepend](https://htmlpreview.github.io/?https://github.com/clarkware/jdepend/blob/master/docs/JDepend.html), [Terraform](https://www.terraform.io)                                                                                                                  |
| 10  | モバイルテスト            | [appium](https://github.com/appium/appium), [Android Studio’s Database Inspector](https://developer.android.com/studio/inspect/database), [Monkey](https://developer.android.com/studio/test/other-testing-tools/monkey?hl=ja), [MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF), [Qark](https://github.com/linkedin/qark) , [Accessibility Scanner](https://play.google.com/store/apps/details?id=com.google.android.apps.accessibility.auditor) |

各スキルについてざっくり説明します。ツールの詳しい内容や使い方については説明しないので、リンク先を参照してください。

#### 手動探索的テスト

リスト化されたテスト項目に従ってアプリケーションを操作して行う古典的な手動テストとは異なり、自動機能テストが存在する前提で、自動化が困難なシナリオを能動的に作成しながら不具合を探し出すのが手動探索的テストです。
書籍ではアプリケーションをより深く理解するために同値分割、境界値分析、状態遷移分析、デシジョンテーブル、決定木、ペアワイズテストといった基本的な分析手法の紹介に加え、探索的にテストを行うための戦略について紹介しています。
また、画面からアプリケーションを操作するだけでなく、API を直接叩いてテストするために Postman や WireMock を使ったり、BugMagnet や Chrome DevTools を使って Web アプリケーションの深いところの問題を発見するためのテクニックについても紹介されています。

#### 自動機能テスト

機能要件をテストし、バグを検出することはテストの基本であり、それらを自動化する自動機能テストは、フルスタックテストのスキルの中でも最も重要です。
フルスタックテストの 10 のスキルセットの他の観点(データテスト、ビジュアルテスト...)も多くは自動化可能であり、そのテクニックは自動機能テストと重なっています。
今日では、UI レイヤー、サービスレイヤー、データベースの各レイヤーで行うテストを自動化する手法は発達しており、多くのツールがあります。
Web アプリケーションの全てのレイヤーを横断的にテストする E2E テストのための Selenium や Cypress、サービスレイヤーの API をテストするための REST-assured や Karate、クラスや関数など最もマイクロなレベルのテストを行う JUnit などが紹介されています。
少し変わったところでは、マイクロサービス間の API の仕様を検証する Contract Testing のための Pact なども紹介されています。

#### 継続的テスト (CI/CD)

テストのシフトレフトを実現するためには、自動機能テストに加え、それらを継続的にテストするための CI/CD の仕組みが不可欠です。
CI(Continuos Integration)はコードリポジトリが変更されるたびに自動機能テストを実行することで、常に回帰テストを行い、品質を維持します。
CD(Continuos Delivery)は、全ての自動機能テストをパスしたら、いつでもアプリケーションをリリースできる状態を保つことです。
書籍では Git によるバージョン管理と、Jenkins による CI パイプラインの実現方法が紹介されています。
また、CI/CD による企業のパフォーマンスを示す指標 [The Four Key Metrics](https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance?hl=en) が紹介されています。

#### データテスト

現代のオンラインサービスは、独自の機能、ユーザーエクスペリエンスデザイン、ブランディング、マーケティングの全てにおいて、データを中心に展開されており、その整合性が保たれない場合、顧客の信頼を損ねることになります。
このため、データの整合性が保たれ、正しく提供されていることを検証するデータのテストは重要です。一方で、様々な種類のデータベースや、キャッシュ、バッチ処理、イベントストリームなど、データを扱う方法は複雑化しており、データテストには特有の難しさがあります。
データテストは、手動探索テスト、自動機能テスト、パフォーマンステスト、データのセキュリティとプライバシーなど、複数の観点にまたがるものです。その上で、データとそのバリエーション、分散性、同時実行性、ネットワーク障害に関するテストを含める必要があります。
書籍では SQL の基本を説明し、手動探索的テストに役立てる方法と、Zerocode による Apache Kafka のイベントストリームのテスト、TestContainer や Deequ によるデータのユニットテストの例が紹介されています。

#### ビジュアルテスト

アプリケーションの「見た目」は非常に重要なポイントです。ボタンの位置がズレていたり、文字が隠れていたりすると、ダメな印象を与え、顧客の信頼を損います。
このため、アプリケーションが設計通りの見た目になっているかを検証するビジュアルテストが重要になります。
自動化しやすいものとして、変更前の画面と変更後の画面を画像比較することにより、差分を検出するビジュアルリグレッションテストがあります。

BackstopJS や Cypress といった Web アプリケーションの E2E テストツールを使ったビジュアルリグレッションテストが紹介されています。
また、Applitools Eyes による AI を使ったビジュアルテストも紹介されています。UI パーツの設計・実装中から見た目を検証し、ビジュアルテストをシフトレフトすることができる Storybook が紹介されています。

#### セキュリティテスト

今日では、多くのアプリケーションがオンラインプラットフォーム上に構築されており、それを狙ったサイバー攻撃が増加しています。
従来のようなリリース直前にセキュリティチェックをかけるだけ、というやりかたでは不十分になってきており、ソフトウェアのライフサイクル全体でセキュリティについて検討し、早期に検証を行うセキュリティのシフトレフトが求められています。
分析フェーズにおいて脅威モデリング手法として [STRIDE モデル](https://www.newton-consulting.co.jp/itilnavi/glossary/stride_model.html)が紹介されています。
セキュリティテストツールとして、OWASP Dependency-Check による静的解析、 OWASP ZAP による動的解析、Snyk IDE Plug-in や Talisman による開発時の解析、 Chrome DevTools と Postman を使った手動探索的テストについて紹介されています。

#### パフォーマンステスト

アプリケーションのパフォーマンスがわずかに低下するだけでも、ビジネスにとって大きな金銭的および評判の損失を引き起こす可能性があります。パフォーマンスを常に計測し、改善できるようにする必要があります。
Web アプリケーションにおいては、バックエンドの API のパフォーマンスと、フロントエンドのパフォーマンスの両方を考慮する必要があり、それぞれに適したツールがあります。
バックエンドに対しては Apache JMeter、Gatling、Apache Benchmark などの自動化ツールを使ってパフォーマンステストをシフトレフトできます。
フロントエンドに対しては、WebPageTest や PageSpeed Insights といったオンライン計測サービスや、Lighthouse のようなローカル実行可能なツールが紹介されています。また、Chrome DevTools を使ってパフォーマンスの計測・分析を行う方法も紹介されています。

#### アクセシビリティテスト

アクセシビリティテストの目的は、ウェブサイトやアプリケーションがすべてのユーザーにとって利用可能であることを確認することです。
W3C WAI は、ソフトウェア開発チームが従うべきウェブコンテンツアクセシビリティガイドライン（WCAG）を策定しているので、開発時には最新のガイドラインを確認し、アクセシビリティを考慮した設計を行うことが重要です。
人手によるテストや、実際にアクセシビリティに課題を持つユーザを対象にしたユーザテストを行うことも重要ですが、多くの Web 開発フレームワークにはアクセシビリティ機能のための組込みサポートがあるので、それらを活用するのも効果的です。
ツールとしては WAVE、 Lighthouse、 Pa11y CI、 Axe-core といったものを使って自動的にアクセシビリティを評価することで、開発サイクルの早期から検証を行うことができます。

#### 機能横断的要件(CFR)テスト

機能横断的要件(Cross-Functional Requirements/CFRs)は、可用性、スケーラビリティ、保守性、可観測性などのアプリケーションの各機能に組み込む必要がある特徴です。
これらは、一般に非機能要件とも呼ばれますが、書籍では、これらの要件はすべてのユーザーストーリーや機能の一部として構築およびテストする必要があること、「非機能」と呼ぶことで、非本質的なものであるかのような印象を与えてしまうことを避けるために、「機能横断的要件」という用語を使っています。
機能横断的要件には、多くの種類がありますが、書籍では、FURPS モデル(Functionality(機能性), Usability(使用性), Reliability(信頼性), Performance(パフォーマンス), Supportability(サポート性))にもとづいた分類で、機能横断的要件をテストする戦略について述べています。
ツールを使ったテスト手法としては、Checkstyle、PMD、 ESLint といった静的解析ツールによって、コードの可読性や保守性といったサポート性の向上、Chaos Toolkit によるカオスエンジニアリングの実践、ArchiUnit や JDepend によるアーキテクチャテスト、Terraform による Infrastructure as Code (IaC)の実践と検証などが紹介されています。

#### モバイルテスト

スマートフォンの登場以来、モバイルデバイスは人々の生活に欠かせないものとなっており、巨大な市場となっています。
モバイルアプリケーションのテストは、スキルセットとしてはこれまで紹介したものと同様のものが求められますが、デバイスや OS の差異、無線ネットワークの特徴など、モバイルテスト特有の条件を考慮する必要があります。
それをふまえて、自動機能テスト、パフォーマンステスト、セキュリティテスト、アクセシビリティテスト、ビジュアルテスト、機能横断的要件テストを含むモバイルレイヤーを完全にテストするための戦略について説明されています。
ツールとしては appium による自動 UI テストやビジュアルテスト、Android Studio’s Database Inspector によるデータテスト、Monkey によるパフォーマンステスト、MobSF によるセキュリティテスト、Accessibility Scanner によるアクセシビリティテストが紹介されています。

## Full Stack Testing 感想

一般にソフトウェア開発で行うべき様々な種類のテストを、幅広く紹介する本というのは意外に少ないので、これを読んだらどんなテストがあるのかだいたい把握できる、という意味では良い本でした。
また、この記事はツールに焦点を置いた紹介になりましたが、書籍では自動化ツールの使い方だけではなく、手動で行う探索的テストの重要性や、なぜそのテストを行うべきなのかという理由、どのようにテスト戦略を立てたらよいのかといったことも詳しく説明されているところも良いです。
個人的には Web フロントエンドのパフォーマンス測定のツールや、アクセシビリティ評価のツールが知れたのが良かったです。

一方で、紹介されているツール群は、やや古くなってしまったものがある感は否めないので、それらをアップデートするとともに、少しだけ触れられている AI/ML アプリケーションのテストなどの話題をカバーした第 2 版の出版と翻訳を期待します。

## 書籍で紹介されていないツール

手動探索的テストにおいては、そもそも手動で行うものなので、ツールによる支援や自動化に関する話はあまりありませんでした。
そこで、探索的テストを支援するためのツール、[LatteArt](https://github.com/latteart-org/latteart/blob/main/README_ja.md) を紹介します。
LatteArt は NTT ソフトウェアイノベーションセンターが提供する OSS で、NTT テクノクロスメンバーも開発に参加しています。

探索的テストのプロセスそのものをツール化するのではなく、下記によって、E2E テストの記録・可視化・分析を支援することで、アジリティの高い効率的なテストを目指す技術で

- テスト記録: テスト中の操作・気付きの記録
- テスト管理: 探索的テストの計画・テスト結果の管理・集計結果の可視化

自動機能テストでカバーできない領域のテストの効率化に、是非お役立てください。

## まとめ

この記事では、書籍「Full Stack Testing」をもとに、ソフトウェアテストで求められるスキルセットと、それに合わせたツールを紹介しました。
全てのスキルやツールを習得するのは大変ですが、どういうシチュエーションのときにどんなテストをすればいいのかの参考になれば幸いです。

明日は@Nitabushi さんの Dify についての記事です！