---
title: "静的テストと動的テストの違い｜静的解析・動的解析で見つかるバグを同じコードで比較"
url: "https://www.issoh.co.jp/tech/details/5254/"
published: 2025-02-10
updated: 2026-11-03
categories: ["テスト"]
publisher: "株式会社一創"
---

# 静的テストと動的テストの違い｜静的解析・動的解析で見つかるバグを同じコードで比較

静的テストと動的テストの違いは、プログラムを実行するかどうかです。静的テストは、コードや仕様書を実行せずに調べて欠陥を直接見つけます。手段は、人が読む「レビュー」とツールで調べる「静的解析」の2つです。動的テストは、プログラムを動かして故障を起こし、そこから原因の欠陥をたどります。この記事では、JSTQBシラバス4.0が挙げる5つの違いで両者を比べたうえで、同じCのコードを静的解析・普通のテスト・AddressSanitizer（実行時のメモリ検査）・カバレッジ計測にかけた実行結果を載せます。どの手段がどのバグを見つけ、どれを見逃したかを出力で確かめられます。ここで扱うのはソフトウェアテストの静的・動的で、構造解析（CAE）やマルウェア解析の用語とは意味が違います（FAQで補足します）。

## まとめ：静的テストと動的テストの違いと使い分けの要点

- **違いの軸は実行の有無**：静的テストは実行せずに欠陥を直接見つけ、動的テストは実行して故障を起こし、分析で欠陥を突き止めます。
- **静的テストの手段は2つ**：要件書や設計書も対象にできるレビュー（人）と、コードを機械的に調べる静的解析（ツール）。「静的検査」「静的コード解析」は後者を指すことが多い言葉です。
- **検出できるかは条件で変わる**：本記事の実測では、テストが通らない経路のNULL渡しはファイル単位の静的解析が、配列の1件多い読み取りは普通のテストを通過したあとAddressSanitizerが報告しました。呼び出し元まで含めて解析すると、静的解析は2つとも報告しました。
- **行カバレッジ100%だけでは欠陥の不在を保証できない**：同じテストで行は100%でも分岐は87.50%で、未通過の1分岐にバグが残っていました。
- **順番は安い検査を前に**：要件・設計はレビュー、コミット時に静的解析、ビルド後に動的テスト。どちらでも見つかる欠陥には両方で対策を入れます。

## 静的テストと動的テストの違い：JSTQBシラバスの5つの観点で比較

ソフトウェアテストの国際資格ISTQBの日本版JSTQBは、[Foundation Levelシラバス（Version 2023V4.0.J02）](https://jstqb.jp/dl/JSTQB-SyllabusFoundation%5FVersionV40.J02.pdf)の3.1.3項で両者の違いを5点にまとめ、冒頭で「静的テストと動的テストの実践は、互いに補完し合っている」と書いています。以下は原文の5点をそのまま表にしたものではなく、説明を整理し、実行の有無と主な手段も加えた比較表です。

| 観点      | 静的テスト           | 動的テスト            |
| ------- | --------------- | ---------------- |
| 実行      | しない（読む・解析する）    | する               |
| 見つけ方    | 欠陥を直接発見         | 故障を起こし分析で欠陥を特定   |
| 得意な欠陥   | めったに通らない経路の欠陥   | 実行時にだけ表れる欠陥      |
| 対象      | 実行できない成果物も可     | 実行できるものだけ        |
| 測れる品質特性 | 保守性など実行に依存しないもの | 性能効率性など実行に依存するもの |
| 主な手段    | レビュー、静的解析       | テストレベル別のテスト、動的解析 |

実務でいちばん効くのは「見つけ方」の行です。シラバス1.1.2項は、静的テストで見つけた欠陥は「再現や診断の必要はない」としています。静的解析の指摘には行番号や問題に至る経路が示されるため、調査の手掛かりになります。ただし、誤検知の確認や修正箇所の判断は必要です。動的テストは利用者が実際に困る現象を捉えますが、落ちた原因を探すデバッグの手間が別にかかります。

3.1.3項には「欠陥の種類によっては、静的テスト、および動的テストのどちらかでしか発見できない」とも書かれています。後半の実測では、同じ2つのバグでも、解析の範囲やテストの入力によってどの手段が報告するかが入れ替わる様子を示します。

### 静的解析と動的解析の違い：ツールが見る対象と出力

ここでは、静的解析と動的解析を、テストを支援するツールによる解析として比較します。静的解析はソースコード（または中間表現）を読み、データの流れや分岐をたどって問題のある書き方を探します。動的解析は、実行中のプログラムにメモリ検査や計測の仕掛けを入れ、実際に起きたアクセスや通過した経路を記録します。

| 項目         | 静的解析                                   | 動的解析                               |
| ---------- | -------------------------------------- | ---------------------------------- |
| 入力         | ソースコード                                 | 実行中のプログラムと入力データ                    |
| 代表ツール      | ESLint、Clang Static Analyzer、SonarQube | AddressSanitizer、Valgrind、llvm-cov |
| セキュリティ検査の例 | SAST                                   | DAST、IAST                          |
| 見られる範囲     | まだ実行していない経路も含む                         | 実際に通った経路だけ                         |
| 出やすい誤り     | 誤検知（問題のない箇所への警告）                       | 見逃し（通らなかった経路）                      |

SASTとDASTの検査方式やCIへの組み込みは、それぞれ[SASTとは？DAST・SCAとの違いとCI/CDへの組み込み・導入判断を実装視点で解説](/tech/details/15880/)と[DASTとは？SASTとの違い・ZAPでのCI/CD組み込みと導入判断を実装視点で解説](/tech/details/15882/)で扱っています。

## 静的テストの2つの手段：レビューと静的解析

[ISTQB Glossaryのstatic testing](https://glossary.istqb.org/en%5FUS/term/static-testing)は、静的テストをテスト対象を実行しないテストと定義しています。シラバス3.1.1項によれば、要件仕様書、ソースコード、テスト計画書、テストケース、プロダクトバックログアイテム、契約書、モデルまで、ほとんどの作業成果物が対象になります。

### レビュー4種別の主導者・目的・形式度

レビューは人が成果物を読み、曖昧さや矛盾、欠落を探す手段です。コードが1行も無い段階でも、レビューなら要件の曖昧さや矛盾を確認できます。シラバス3.2.4項は4つの種別を挙げています。

| 種別        | 主導者      | 主な目的      | 形式度  |
| --------- | -------- | --------- | ---- |
| 非形式的レビュー  | 定めなし     | 不正の検出     | 低い   |
| ウォークスルー   | 作成者      | 教育・合意形成など | 中    |
| テクニカルレビュー | モデレーター   | 技術的な合意と判断 | 中〜高  |
| インスペクション  | レビューリーダー | 不正を最大数発見  | 最も高い |

日常のプルリクエストは非形式的レビュー、アーキテクチャ変更はテクニカルレビュー、決済や医療など監査証跡が要る領域の要件書はインスペクション、という割り当てから始めると過不足が出にくくなります。インスペクションでは作成者がレビューリーダーや書記を兼ねられません。進め方の土台は[ISO/IEC 20246:2017（Work product reviews）](https://www.iso.org/standard/67407.html)の汎用プロセス（2022年の見直しで現行版のまま確認）で、シラバスはこれを計画・レビューの立ち上げ・個々人のレビュー・共有と分析・修正と報告の5活動に要約しています。コードを対象にした運用は[コードレビューとは？目的・観点・進め方と実装現場の運用設計を解説](/tech/details/13384/)にまとめています。

### 静的テストで早期に見つかる欠陥と静的解析の対象条件

静的解析はツールでコードを調べる手段です。シラバス3.1.3項は、静的テストで早期または安価に見つかる欠陥として次を挙げています。

- 要件の欠陥（不整合・曖昧さ・矛盾・欠落・不正確さ・重複）
- 設計の欠陥（非効率なデータベース構造、不十分なモジュール化）
- コードの欠陥（値が定義されていない変数、到達不能コード、重複コード、過剰な複雑度）
- 標準からの逸脱（命名規則違反など）
- インターフェース仕様の誤り（パラメーターの数・種類・順序の不一致）
- 特定の種類のセキュリティ脆弱性（バッファオーバーフローなど）
- テストベースに対するカバレッジの不足（受け入れ基準に対応するテストケースの欠落）

このうち要件・設計・カバレッジ不足は、多くの場合コードが無くても見つかるレビューの守備範囲です。コードの静的解析には解析可能な構造が必要ですが、静的解析ツールにはスペルや可読性を調べるものも含まれます。自然文の要件書についても、ツールの対応範囲で表記や文章上の問題を検査できます。静的解析の仕組み（構文木・データフロー解析）と言語別のツールは[静的解析とは？実行せずに欠陥を見つける仕組みとツールの選び方](/tech/details/7475/)で解説しています。

## 動的テストの手法：テストレベル・技法・動的解析

動的テストはプログラムを実行して結果を確かめるテストの総称で、「どの範囲を動かすか（テストレベル）」「どう入力を選ぶか（技法）」「実行中に何を測るか（動的解析）」の3つの軸で整理できます。

### テストレベル別の動的テストと代表的なツール

シラバス2.2.1項は5つのテストレベルを挙げています。

| テストレベル       | 焦点            | ツール・環境・実施者の例             |
| ------------ | ------------- | ------------------------ |
| コンポーネントテスト   | 関数・クラス単体      | JUnit、pytest、Jest、Vitest |
| コンポーネント統合テスト | 部品間のインターフェース  | 同上＋テストダブル                |
| システムテスト      | システム全体の機能・非機能 | Playwright、Selenium、k6   |
| システム統合テスト    | 外部システムとの接続    | 本番相当の環境                  |
| 受け入れテスト      | 業務ニーズを満たすか    | 想定ユーザーによる確認              |

テストピラミッドでは、小さく分離されたテストを多く配置し、実行時間の長い上位レベルのテストを絞ります。ただし、テスト件数の比率と必要工数の比率は同じではなく、工数は対象のリスクと環境準備・保守の負担から決めます。E2Eの範囲とツール選びは[E2E（エンドツーエンド）テストのベストプラクティス｜結合テストとの違いとツール選定](/tech/details/5470/)、負荷テストの実行例は[k6とは？負荷テストの使い方とインストール手順【v2.3対応】](/tech/details/7581/)、発注側から見た工程の流れは[システム開発のテスト工程とは？種類・流れとV字モデル・発注者が見る判断軸](/column/details/13445/)が詳しいです。

### ブラックボックス・ホワイトボックスの技法とカバレッジ計測

入力の選び方には、仕様から選ぶブラックボックステスト技法（同値分割法・境界値分析など）と、コードの構造から選ぶホワイトボックステスト技法（ステートメントテスト・ブランチテスト）があります。このほか、エラー推測や探索的テストなどの経験ベースのテスト技法もあります。シラバス4.3項は「ブランチカバレッジはステートメントカバレッジを包含する」とし、逆は成立しないと明記しています。ステートメントカバレッジだけでは、未通過の分岐が残ることがあります。次章の実測がその例です（llvm-covが測る行カバレッジは行単位の指標で、文単位のステートメントカバレッジとは厳密には別物です）。技法の詳細は[ブラックボックステストとホワイトボックステストの違い｜技法・カバレッジ基準・使い分け](/tech/details/6782/)、計測ツールと目標値の決め方は[テストカバレッジとは？C0/C1/C2の網羅率と計測ツール・目標設定を実装者向けに解説](/tech/details/13507/)を参照してください。

### 動的解析ツール：メモリ検査・カバレッジ・実機での計測

テストの合否だけでは見えない問題を拾うのが動的解析です。C/C++では[AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html)が代表で、公式ドキュメントはヒープ・スタック・グローバル変数の範囲外アクセス、解放後の使用、二重解放などを検出対象に挙げ、典型的な速度低下を「2x」としています。メモリリークの検出はLinuxでは既定で有効、macOSでは`ASAN_OPTIONS=detect_leaks=1`の指定が必要です。組込み開発では、実機上で関数の通過や処理時間を記録するトレース型の動的テストツールが使われ、シミュレーターでは再現しないタイミング依存の不具合を追う手段になります。クラッシュ時の調べ方は[セグメンテーションフォルト（Segmentation fault）の原因と調べ方｜core dumpedの意味・gdb・ASan](/tech/details/7982/)、リークの特定は[メモリリークとは？原因の特定方法と直し方を4言語の再現コードで解説](/tech/details/3621/)で扱っています。

## 同じCコードで比較：静的解析と動的テストが見つけるバグ・見逃すバグ

ここからは、2つのバグを仕込んだCのコード（lib.c）を、静的解析・普通のテスト・AddressSanitizer・分岐カバレッジの4つにかけた結果です。環境はApple clang 21.0.0（macOS・x86\_64）で、2026年10月21日に実行しました。

```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* 在庫数の合計を返す（count 件を足すはずが <= で1件多く読む） */
int sum_stock(const int *items, int count) {
    int total = 0;
    for (int i = 0; i <= count; i++) {
        total += items[i];
    }
    return total;
}

/* ステータスコードに対応する文言の長さを返す */
int message_length(int code) {
    const char *msg = NULL;
    if (code == 200) msg = "OK";
    else if (code == 404) msg = "Not Found";
    else if (code == 500) msg = "Internal Server Error";
    /* 想定外のコードでは msg が NULL のまま strlen に渡る */
    return (int)strlen(msg);
}
```

テスト（test\_stock.c）は、仕様どおりの入力だけを確かめる素直なものにしました。

```
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

int sum_stock(const int *items, int count);
int message_length(int code);

int main(void) {
    int *items = malloc(sizeof(int) * 3);
    items[0] = 1; items[1] = 2; items[2] = 3;
    assert(sum_stock(items, 3) == 6);
    assert(message_length(200) == 2);
    assert(message_length(404) == 9);
    assert(message_length(500) == 21);
    free(items);
    puts("all tests passed");
    return 0;
}
```

### 静的解析の結果：テストが通らない経路のNULL渡しを検出

コンパイラの警告（`-Wall -Wextra`）は何も出しませんでした。Clang Static Analyzerにかけると、テストが一度も通らない「想定外のコード」の経路を見つけます。

```
$ clang -Wall -Wextra -c lib.c      # 警告なし
$ clang --analyze lib.c
lib.c:21:17: warning: Null pointer passed as 1st argument to string length function [unix.cstring.NullArg]
   21 |     return (int)strlen(msg);
      |                 ^~~~~~~~~~~
1 warning generated.
```

シラバス3.1.3項の「動的テストではほとんど実行されない、あるいは到達しにくいコード内のパスに潜む欠陥を、より簡単に検出することがある」がそのまま出た形です。[Clangのチェッカー一覧](https://clang.llvm.org/docs/analyzer/checkers.html)によると、unix.cstring.NullArgはstrlenなどC文字列関数へのNULL渡しを調べます。一方で、lib.cだけを解析したときは`sum_stock`の1件多い読み取りに何も言いませんでした。`items`の大きさが関数の中からは分からないためです。

解析器に呼び出し元も見せると、結果が変わります。lib.cとtest\_stock.cの`main`を1つのファイル（combined.c）にまとめて解析すると、NULL渡しに加えて9行目にも警告が出ました。

```
$ clang --analyze combined.c
combined.c:9:15: warning: Assigned value is uninitialized [core.uninitialized.Assign]
    9 |         total += items[i];
      |               ^  ~~~~~~~~
combined.c:21:17: warning: Null pointer passed as 1st argument to string length function [unix.cstring.NullArg]
2 warnings generated.
```

`main`が3件分だけ値を入れた領域の4件目を読む経路を、呼び出し元からたどれたためです。範囲外読み取りという名前ではなく「未初期化値の代入」として報告される点は、出力を読むときに気をつけたいところです。静的解析で警告が出ないことは、解析器に見せた範囲で見つからなかったという意味にとどまります。

### 普通のテストとAddressSanitizerの結果：通るテストの裏の範囲外読み取り

今回の環境で普通にビルドして実行した際は、4つのassertがすべて通りました。ただし、範囲外読み取りは未定義動作であり、同じ結果の再現は保証されません。

```
$ clang -O0 lib.c test_stock.c -o t_plain && ./t_plain
all tests passed
```

`sum_stock`は確保した3件の外側にある4件目を読んでいますが、この実行ではその値がたまたま0で、合計が期待値の6と一致しました。同じテストを`-fsanitize=address`付きでビルドすると、AddressSanitizerが範囲外の読み取りを捉えてプログラムを止めます（終了コード134）。

```
$ clang -O0 -g -fsanitize=address lib.c test_stock.c -o t_asan && ./t_asan
==53654==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000000dc ...
READ of size 4 at 0x6020000000dc thread T0
    #0 0x000105f7580f in sum_stock lib.c:9
    #1 0x000105f75a00 in main test_stock.c:11
0x6020000000dc is located 0 bytes after 12-byte region [0x6020000000d0,0x6020000000dc)
SUMMARY: AddressSanitizer: heap-buffer-overflow lib.c:9 in sum_stock
```

12バイト（int 3件）の領域の直後を4バイト読んだ、という具体的な報告です。動的テストはテストを書けば終わりではなく、どんな仕掛けを入れて動かすかで検出力が大きく変わります。

### カバレッジの結果：行100%でも分岐87.50%

このテストでどこまで通ったかをllvm-covで測ると、行カバレッジは100%でした。分岐で見ると1つ通っていません。macOSのCommand Line Toolsを使い、llvm-profdataやllvm-covがPATHにない場合は、以下の各コマンドをそれぞれxcrun llvm-profdata、xcrun llvm-covとして実行します。

```
$ clang -O0 -fprofile-instr-generate -fcoverage-mapping lib.c test_stock.c -o t_cov
$ LLVM_PROFILE_FILE=t.profraw ./t_cov
$ llvm-profdata merge -o t.profdata t.profraw
$ llvm-cov report ./t_cov -instr-profile=t.profdata lib.c --show-branch-summary
Filename   ...  Lines  Missed Lines   Cover   Branches  Missed Branches   Cover
lib.c      ...     14             0 100.00%          8                1  87.50%

$ llvm-cov show ./t_cov -instr-profile=t.profdata lib.c --show-branches=count
   19|      1|    else if (code == 500) msg = "Internal Server Error";
  |  Branch (19:14): [True: 1, False: 0]
```

未通過の「False: 0」が、静的解析の指摘したNULL渡しの経路です。行カバレッジ100%を合格基準にしていたら、このバグは通過していました。

| 手段                           | NULL渡し（通らない経路） | 1件多い読み取り     |
| ---------------------------- | -------------- | ------------ |
| コンパイラ警告 `-Wall -Wextra`      | 見逃し            | 見逃し          |
| `clang --analyze`（lib.c単体）   | 検出             | 見逃し          |
| `clang --analyze`（テストと1ファイル） | 検出             | 検出（未初期化値として） |
| 普通のテスト                       | 見逃し（入力に無い）     | 見逃し（全件合格）    |
| テスト＋AddressSanitizer         | 未評価（先行エラーで停止）  | 検出           |
| テスト＋分岐カバレッジ                  | 未通過として可視化      | 見逃し          |

今回の条件で2つとも報告したのは、呼び出し元まで含めた静的解析だけでした。ただし片方は「未初期化値」という別の名前で、ファイル単位の解析では出ていません。テストの側も、想定外のステータスコードを渡す異常系のテストを1本足せばNULL渡しで落ちます。どの手段も、検出できるかは解析の範囲・入力・仕掛けで決まります。1つの手段の「問題なし」を品質の証明にせず、静的解析とサニタイザ付きのテスト、境界値と異常値の入力を重ねるのが、この実測から引き出せる運用です。

## ESLint v10とテストをCIで順に回す設定例

JavaScriptでは、静的解析をESLint、動的テストをJestやVitestで回し、CIで静的解析を先に置く構成が基本です。以下の設定はJavaScript向けで、TypeScriptを解析する場合は[typescript-eslint](https://typescript-eslint.io/users/configs/)のパーサーと設定を追加します。ESLintはnpmの最新版が10.13.0（2026年10月16日公開）で、`engines.node`は`^20.19.0 || ^22.13.0 || >=24`です。[v10の移行ガイド](https://eslint.org/docs/latest/use/migrate-to-10.0.0)のとおり旧形式の`.eslintrc.*`は読まれないため、設定は`eslint.config.js`に書きます。

```
npm install --save-dev eslint @eslint/js
```

次の内容を、プロジェクト直下の`eslint.config.js`に保存します。

```
import js from "@eslint/js";
import { defineConfig } from "eslint/config";

export default defineConfig([
  js.configs.recommended,
  {
    files: ["**/*.js"],
    languageOptions: { globals: { console: "readonly" } },
  },
]);
```

package.jsonに`"type": "module"`が無いプロジェクトでは、ファイル名を`eslint.config.mjs`にします。次のコードを解析すると、[no-unused-vars](https://eslint.org/docs/latest/rules/no-unused-vars)が未使用の変数を指摘し、終了コード1で止まります（ESLint 10.13.0・Node.js v26.5.0で確認）。

```
// sample.js
function calc(a, b) {
  const unused = 0;
  return a + b;
}
console.log(calc(1, 2));

$ npx eslint sample.js
  3:9  error  'unused' is assigned a value but never used  no-unused-vars

✖ 1 problem (1 error, 0 warnings)
```

CI例は、package-lock.jsonをコミットし、package.jsonのscripts.testにテスト実行コマンドを設定したプロジェクトを前提とします。静的解析のジョブが通ったときだけテストに進めます。`needs: lint`の1行により、ESLintがエラーを検出して失敗した場合はテストジョブが起動しません。警告だけの場合は、この設定ではテストへ進みます。

```
# .github/workflows/ci.yml
name: ci
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
      - run: npm ci
      - run: npx eslint .
  test:
    needs: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
      - run: npm ci
      - run: npm test
```

actions/checkoutはv7.0.1（2026年7月20日）、actions/setup-nodeはv7.1.0（2026年10月8日）が最新リリースです。既存コードで警告が数千件出る場合は、全ルールを一度に有効にせず、新規コードだけを厳しく見るベースライン運用から始めます。誤検知が生まれる仕組みと抑え方は[静的コード解析の誤検知と限界｜レビュー・テストとの責任分担](/tech/details/7475/)、ESLintの設定全般は[ESLintとは？VSCodeでの設定からflat config・Prettier連携まで解説【ESLint v10対応】](/tech/details/3286/)、多言語の品質ゲートは[SonarQube（ソナーキューブ）とは？できること・料金・使い方と品質ゲートの設定【2026年10月】](/column/details/2988/)で扱っています。

## 静的テストと動的テストの工数配分を決める判断基準

### 静的テストを先に厚くする開発の条件

次に当てはまる開発では、レビューと静的解析への投資を先に厚くします。1つ目は、要件の誤りが後工程で高くつく受託開発や基幹システムです。シラバス3.2.4項は、レビューの形式度を成果物の重要性、規制上の要件、監査証跡の必要性で決めるとしています。2つ目は、複数人が同じコードベースに長く書き込む保守案件で、規約と静的解析が読みやすさの最低線を支えます。3つ目はC/C++のようにメモリ安全性を言語が保証しない開発です。今回の実測でも、ファイル単位の静的解析とサニタイザは別々のバグを報告しました。両方をCIに入れ、異常値や境界値のテストも足します。

### 動的テストへ寄せる開発と、両方で対策すべき欠陥

本番データや外部システムに接続せず、検証後に破棄する低リスクのプロトタイプでは、形式的なレビューを省き、推奨ルールのリンターだけを入れて、残りの工数を動作確認へ回します。性能・同時実行・外部APIとの結合が主なリスクのシステムも、静的解析の警告ゼロは品質の証明にならないので、負荷テストと統合テストを先に整えます。例えばk6で応答時間とエラー率を測定し、外部APIとの統合テストではタイムアウト時やエラー応答時の処理を確認します。

リリース後に見つかった不具合は、静的テストと動的テストのどちらで止められたかを振り返ると、次の配分が決まります。両方で止められたはずの不具合なら、両方に対策を入れます。「上流のレビューで直せば十分」と片方だけにすると、似た不具合が別の経路で抜けてきます。テストとCI/CDの整備を運用ごと任せたい場合は、一創の[DevOps・CI/CD導入支援](/service/system/devops/)で、パイプラインの設計から社内チームへの引き継ぎまで支援しています。

## 静的テストと動的テストのよくある質問

### 静的テスト・静的検査・静的解析は同じ意味ですか？

重なりますが範囲が違います。静的テストはレビューと静的解析を含む総称で、「静的検査」「静的コード解析」はツールによる解析を指すことが多い言葉です。セキュリティ検査には、コードなどを実行せずに調べるSAST、稼働中のアプリケーションを外部から調べるDAST、内部計測を使うIASTなどがあります。

### 動的テストにはどんな手法がありますか？

範囲で分けるとコンポーネントテスト、コンポーネント統合テスト、システムテスト、システム統合テスト、受け入れテストの5つです。テスト技法にはブラックボックス技法、ホワイトボックス技法、経験ベースの技法があり、実行中の計測としてAddressSanitizerのようなメモリ検査やカバレッジ計測があります。

### 静的解析ツールとコンパイラの警告は何が違いますか？

コンパイラ警告も静的解析の一種で、解析の深さはツールやオプションによって異なります。GCCの-fanalyzerのように経路を追う機能もあれば、ESLintのように構文や規則の検査を中心とするツールもあります。本記事の実測では、`-Wall -Wextra`が無警告だったコードで、Clang Static AnalyzerがstrlenへのNULL渡しを見つけました。

### 構造解析やマルウェア解析の「静的解析・動的解析」とは別物ですか？

別物です。構造解析（CAE）では、荷重が時間で変わらないとみなして変形や応力を求める解析を静的解析（静解析）、慣性や時間変化を含める解析を動的解析（動解析）と呼びます。マルウェア解析では、検体を実行せずに中身を調べるのが静的解析、隔離環境で実行して挙動を観察するのが動的解析です。ソフトウェアテストやマルウェア解析では対象プログラムの実行の有無を区別します。構造解析では慣性や減衰などの動的効果を扱うかを区別するため、同じ判定軸ではありません。

### 静的テストだけで品質は十分ですか？

十分ではありません。JSTQBシラバスも、欠陥の種類によってはどちらかでしか発見できないとしています。本記事の実測でも、ファイル単位の静的解析は配列の範囲外読み取りを報告せず、AddressSanitizerを入れた動的テストが報告しました。性能や同時実行の問題は実行しないと測れないため、両方を工程に組み込みます。

## 関連記事

- [静的解析とは？実行せずに欠陥を見つける仕組みとツールの選び方](/tech/details/7475/)
- [静的コード解析の誤検知と限界｜レビュー・テストとの責任分担](/tech/details/7475/)
- [ブラックボックステストとホワイトボックステストの違い｜技法・カバレッジ基準・使い分け](/tech/details/6782/)
- [テストカバレッジとは？C0/C1/C2の網羅率と計測ツール・目標設定を実装者向けに解説](/tech/details/13507/)
- [DASTとは？SASTとの違い・ZAPでのCI/CD組み込みと導入判断を実装視点で解説](/tech/details/15882/)

---

出典: [静的テストと動的テストの違い｜静的解析・動的解析で見つかるバグを同じコードで比較](<https://www.issoh.co.jp/tech/details/5254/>)（株式会社一創）
