静的解析と動的テストの違いとは|検出できるバグ・代表ツール・使い分けを比較
静的解析(静的検査)と動的テストは、どちらもソフトウェアの品質を上げる手法ですが、コードを「実行せずに調べる」か「実行して確かめる」かで役割がはっきり分かれます。この記事では、両者の違いを解析タイミング・検出できるバグ・対象範囲の観点で比較し、ESLintやSonarQube、Jest、Seleniumといった代表ツール、CI/CDでの使い分け、導入時につまずきやすい誤検知への対処までを整理します。
まとめ:静的解析と動的テストの使い分け
結論から示します。両者は競合ではなく補完関係で、開発の段階を分けて両方使うのが基本です。
- 静的解析(静的検査/SAST):コードを実行せずに構文・規約違反・脆弱性を検出。開発初期〜コミット時に効く。
- 動的テスト(DAST含む):実行して挙動を検証。メモリリークや性能問題など、動かさないと分からないバグを検出。
- 検出領域が違う:未使用変数やSQLインジェクションは静的、スレッド競合や負荷時のクラッシュは動的。片方では穴が残る。
- 入れる順番:コミット時に静的解析、CI/CDのビルド段階で動的テスト、というシフトレフトが定番。
- つまずき所:静的解析の誤検知(False Positive)を放置するとルールが形骸化する。段階導入と例外設定が要。
以降で、定義・比較表・代表ツール・使い分け・誤検知対策の順に解説します。
静的解析と動的テストとは|実行しない検査と実行する検証
用語を先に揃えます。「静的検査」「静的テスト」「静的コード解析」はほぼ同義で、いずれもコードを実行せずに調べる手法を指します。本記事では一般的な「静的解析」に統一します。対になるのが、実行して確かめる「動的テスト」です。
静的解析(静的検査):ソースコードを実行せずに調べる
静的解析は、ソースコードの構文や論理構造を解析し、バグの芽や規約違反を実行前に見つける手法です。未使用変数、命名規則違反、到達不能コード、SQLインジェクションのような脆弱性パターンなどが対象になります。コンパイルや実行を伴わないため、書いた直後やコミット時に軽く回せるのが利点です。セキュリティ分野ではSAST(Static Application Security Testing)とも呼ばれます。
動的テスト:実際に動かして挙動を確かめる
動的テストは、プログラムを実行し、入力に対する出力や挙動が期待どおりかを検証します。ユニットテスト、統合テスト、負荷テスト、セキュリティテスト(DAST)などが含まれます。実行時にしか現れないメモリリーク、スレッド競合、特定負荷でのクラッシュなどを捉えられる一方、実行環境の準備や実行時間というコストがかかります。
静的解析と動的テストの違い|タイミング・検出できるバグ・対象
もっとも検索されているのが、この「違い」です。観点ごとに整理します。
| 観点 | 静的解析(静的検査) | 動的テスト |
|---|---|---|
| 実行 | しない(コード解析) | する(実行して検証) |
| タイミング | 開発初期・コミット時 | ビルド後・リリース前 |
| 得意なバグ | 構文・規約・脆弱性パターン | 実行時バグ・性能・競合 |
| 対象 | 可読性・保守性・セキュリティ | 動作の正しさ・耐負荷 |
| コスト | 低い(高速・自動化容易) | 高い(環境・時間が必要) |
表のとおり、両者は「どの段階で何を見つけるか」が違います。静的解析は早く・広く・浅く、動的テストは遅く・深く・実態に即して検出します。だからこそ、どちらか一方では品質の穴が残り、両方を段階的に組み合わせる必要があります。
静的解析と動的テストで検出できるバグの具体例|未使用変数とメモリリーク
抽象論ではイメージしにくいので、実例で対比します。静的解析が見つけるのは「コードを読めば分かる問題」、動的テストが見つけるのは「動かさないと分からない問題」です。
静的解析の典型は、未使用変数・到達不能コード・命名規則違反のほか、SQLインジェクションやクロスサイトスクリプティング(XSS)のような既知の脆弱性パターンです。たとえば次のような未使用変数は、ESLintなら一瞬で指摘します。
// sample.js(静的解析が指摘する典型例)
function calc(a, b) {
const unused = 0; // 使われていない変数
return a + b;
}
console.log(calc(1, 2));
$ npx eslint sample.js
sample.js
3:9 warning 'unused' is assigned a value but never used no-unused-vars
✖ 1 problem (0 errors, 1 warning)
一方、動的テストでしか捉えられないのは、メモリリーク、スレッド競合(デッドロック)、特定の負荷でのみ顕在化する性能ボトルネックやクラッシュです。これらは「正しく書けているように見える」コードで起きるため、実行して初めて分かります。検出領域が重ならないことが、両方を使う最大の理由です。
代表的な静的解析ツール|ESLint・SonarQube・言語別の選択
静的解析ツールは言語ごとに定番があります。JavaScript/TypeScriptはESLint、多言語横断の品質可視化はSonarQube、PythonはPylintやmypy、JavaはCheckstyleやSpotBugs(旧FindBugs)、PHPはPHPStanやPsalmが広く使われます。
ESLintは2024年4月のv9で設定形式が刷新され、フラットコンフィグ(eslint.config.js)が既定となり、従来の.eslintrcは非推奨になりました。これから導入するならフラットコンフィグ前提で構成します。PHPの静的解析でPHPStanとPsalmのどちらを選ぶか迷う場合は、PsalmとPHPStanの比較:機能や使用感の違いを検証で具体的な違いを確認できます。静的解析を含むコード品質管理の全体像は静的コード解析と他のコード品質管理手法との違いも参考になります。
代表的な動的テストの手法とツール|単体・E2E・負荷・DASTの使い分け
動的テストは目的別に手法が分かれ、それぞれ定番ツールがあります。重要度の高い順に整理します。
まず土台になるのがユニットテスト(単体テスト)で、関数やメソッド単位の正しさを検証します。JavaScriptならJest、JavaならJUnit、PythonならPyTestが定番です。次に統合テストで、モジュール間やAPIの連携を確認します。WebのE2EではSeleniumやCypressが使われます。負荷・性能テストにはApache JMeterやGatling、実行時のセキュリティ検証(DAST)にはOWASP ZAPやBurp Suiteを用います。DASTの検査原理とCI/CDへの組み込みはDASTとは?SASTとの違い・ZAPでのCI/CD組み込みと導入判断を実装視点で解説で扱っています。すべてを同程度にやる必要はなく、ユニットテストを厚く、負荷・セキュリティは要件に応じて、という配分が現実的です。
CI/CDでの組み合わせと使い分け|シフトレフトの実践
両者は入れる順番が肝心です。シフトレフト(テストを開発の早い段階へ前倒しする考え方)が定石です。具体的には、コードのコミットやプッシュの段階で静的解析を自動実行し、規約違反や脆弱性パターンを即座に弾きます。その後、CI/CDのビルド段階でユニットテスト・統合テストを回し、リリース前に負荷テストやDASTを実施します。
順番を逆にすると効率が落ちます。実行コストの低い静的解析を後ろに置くと、動かしてから初歩的な規約違反が見つかり手戻りが増えます。安いチェックを前、重いチェックを後ろ、が鉄則です。GitHub ActionsやJenkinsで、プッシュ時にESLintやSonarQube、ビルド時に自動テスト、という二段構えにするのが標準的な構成です。
静的解析の導入でつまずく誤検知への対処
静的解析の導入が失敗する最大の原因は、誤検知(False Positive)の放置です。実際には問題のないコードまで警告されると、開発者は警告全体を無視し始め、本当に危険な指摘も見逃されます。ルールが形骸化した静的解析は、入れていないのとほとんど変わりません。
対策は段階導入です。最初から全ルールを最大強度で有効化せず、まず重大度の高いルール(脆弱性・明確なバグ)に絞って導入し、誤検知が多いルールは無効化するか個別に例外設定します。既存コードの大量の警告は、基準時点を区切って「新規コードのみ厳格にチェックする」運用(ベースライン)にすると現実的です。静的解析は「全警告ゼロ」を目指す道具ではなく、危険な変更を止める道具だと割り切ると、定着します。逆に、誤検知を放置したまま警告件数だけを追うチームでは、まず導入すべきでないルールを外すところから始めるべきです。
よくある質問(FAQ)
静的検査と静的解析は同じ意味ですか?
ほぼ同義です。「静的検査」「静的テスト」「静的コード解析」はいずれも、コードを実行せずに構文や脆弱性を調べる手法を指します。セキュリティ文脈ではSAST(静的アプリケーションセキュリティテスト)とも呼ばれます。対義語が、実行して確かめる「動的テスト(DAST含む)」です。
静的解析と動的テストの違いは何ですか?
コードを実行するかどうかが本質的な違いです。静的解析は実行せずに構文・規約・脆弱性パターンを早期に検出し、動的テストは実行してメモリリークや性能問題など実行時のバグを検出します。検出できるバグの領域が重ならないため、両方を併用します。
静的解析だけで品質は十分ですか?
不十分です。静的解析はコードを読めば分かる問題に強い一方、実行時にしか現れないメモリリーク・スレッド競合・負荷時のクラッシュは検出できません。これらは動的テストでしか捉えられないため、静的解析と動的テストの併用が前提になります。
静的解析ツールのおすすめは何ですか?
言語で選びます。JavaScript/TypeScriptはESLint(v9以降はフラットコンフィグ)、多言語の品質可視化はSonarQube、PythonはPylintやmypy、JavaはCheckstyle・SpotBugs、PHPはPHPStan・Psalmが定番です。まず1つを軽く導入し、誤検知を見ながらルールを育てるのが失敗しにくい進め方です。
シフトレフトとは何ですか?
テストや品質チェックを開発工程の早い段階(左側)へ前倒しする考え方です。コミット時に静的解析、ビルド時に自動テストを回すことで、バグを早期かつ低コストで発見できます。後工程ほど修正コストが膨らむため、安いチェックを前に置くのが要点です。