A Capacitor release can pass its end-to-end checks and still ship a broken invoice calculation, stale feature flag, or platform-specific branch. The failure often starts earlier: a unit test still reflects the old behavior, a mock hides a changed dependency, or CI runs a different environment from the developer’s machine. By the time the bug reaches a phone or Electron desktop build, the test suite has provided confidence without providing protection.
そのため Jest単体テスト Jest単体テストは、実行コマンドとしてではなく、生きたワークフロー決定として扱うべきです。有用な質問は実用的なものです: 開発者は失敗を信頼できる速度で、どの境界が孤立するべきか、CIでどのカバレッジが含まれるべきか、Jestはプロジェクトのモジュールシステムとフィードバックの期待に合致しているかどうか、というものです。このガイドでは、Nodeサービス、Webアプリケーション、Capacitor プロジェクト、Electronアプリケーションを横断するこの決定について説明します。より広いコンテキストについては、自動チェックが配達にどのように組み込まれるかについての説明を参照してください。 自動テストの現代的なソフトウェアワークフロー.

ワークフロー決定、古いテストのバグ、現代的なテスト戦略を概説したインフォグラフィック。
- 目次
- 2026年に Jest 単体テストがまだ重要なのか
- ブラウザ Shim を __CAPGO_KEEP_0__ に必要なだけ追加する
- 最初の信頼できる単体テストを書く
- JestとCI、カバレッジゲートの統合
- 大規模なスケールでJestユニットテストを信頼できるようにする
- チームのための決定フレームワークと次のステップ
2026年にJestユニットテストはまだ重要な理由
Jestは、単にアサーションシンタックスを解決するのではなく、チームに、ビジネスロジックを確認するための繰り返し可能な場所、依存性の境界を制御する、カバレッジの期待を強制する、そしてユーザーに到達する前にモバイルまたはデスクトップパッケージを実行する前にチェックを実行するためのフローを提供する。 これらのワークフローは、ブラウザシェル、Capacitor WebView、Electronレンダラー、Nodeプロセス、プラットフォームAPIの周りで異なるJavaScript動作を実行する場合に重要です。
Jestの採用は歴史的にも重い。Facebookは 2011 でJavaScriptチャットのリライト用に作成し、 2014でオープンソース化し、OpenJS Foundationは、 38,000 GitHub stars and 17 million weekly downloads by 2022、2022年までに 43,000 stars and 21 million weekly downloads by 2024 (OpenJS FoundationのJestプロジェクトの歴史)
Those figures don’t prove that Jest is right for every new repository, but they explain why teams often inherit a mature ecosystem, familiar conventions, and a large pool of existing examples.
ユニットテストをスキップし、エンドツーエンドのカバレッジに焦点を当てることは、短期的には安いように見えるが、すべての小さなエラーが、全アプリケーション起動、デバイス設定、ネットワークパス、プラットフォーム固有の診断を必要とするまで、コストが高くなる。 E2Eテストはリリースクリティカルなジャーニーに値打ちがありますが、タックス計算、更新マニフェスト、パーミッションの決定、ストレージアダプター、エラーマッピングなどの迅速で集中したチェックの代わりにはならない。
実践的なルール:
Jestのエコシステムが移行リスクを軽減し、スイートが開発者に信頼できるフィードバックを提供する場合、Jestを維持してください。ランナー自体が毎日ボトルネックになっている場合、別のランナーを検討してください。
最小の構成から始めましょう。Nodeサービスは通常、Jestのデフォルト環境とテストスクリプトが必要です。ブラウザ向けのCapacitorまたはElectronモジュールはDOMのようなグローバル変数が必要です。TypeScriptは、デバッグ、モジュールの互換性、起動動作に影響を与える可能性がある変換決定を追加します。
Nodeプロジェクトの場合、パッケージを初期化し、Jestを開発依存としてインストールします。
npm init -y
npm install --save-dev jest
npx jest --init
生成された構成は、設計決定ではありません。テスト環境、変換、モジュールエイリアス、セットアップファイルを確認し、コミットする前に確認してください。
TypeScriptの変換を意図的に選択してください。
ts-jest 既存のリポジトリがTypeScriptコンパイラの動作に依存し、開発者が熟知の診断を望む場合、便利です。 @swc/jest トランスパイル速度が重要な場合、既存のタイプチェッキングが別のコマンドとして実行されている場合、魅力的です。どちらのオプションもタイプチェッキングを置き換えず、ESM重視のパッケージは、変換器に関係なく追加の構成が必要になる可能性があります。
| オプション | Node | TypeScript | Capacitor/Electron |
|---|---|---|---|
| 環境 | node |
node またはプロジェクト固有の |
jsdom DOM向けのcode |
| 変換 | 通常は何もありません | ts-jest または @swc/jest |
TypeScript変換プラスDOMセットアップ |
| ESMの取り扱い | パッケージ形式のマッチ | トランスフォーマーへのサポートの確認 | プラグイン依存関係とモジュールエイリアスの確認 |
| 通常のセットアップ | 最小限 | jest.config.ts |
setupFilesAfterEnvモック、ブラウザAPI |
A TypeScript configuration using ts-jest can look like this:
import type { Config } from 'jest'
const config: Config = {
preset: 'ts-jest',
testEnvironment: 'node',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
clearMocks: true,
collectCoverageFrom: ['src/**/*.{ts,tsx}'],
}
export default config
For Babel-based JavaScript or mixed repositories, keep the Babel file explicit:
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
'@babel/preset-typescript',
],
}
Add only the browser shims your code needs
Capacitor and Electron tests frequently import code that expects window.matchMedia or IntersectionObserverCapacitorのライブアップデートの代替手段は、以下の点で異なります。
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: (query: string) => ({
matches: false,
media: query,
onchange: null,
addListener: () => {},
removeListener: () => {},
addEventListener: () => {},
removeEventListener: () => {},
dispatchEvent: () => false,
}),
})
class MockIntersectionObserver {
observe() {}
unobserve() {}
disconnect() {}
}
Object.defineProperty(window, 'IntersectionObserver', {
writable: true,
value: MockIntersectionObserver,
})
Capacitorのライブアップデートの代替手段は、以下の点で異なります。 transformIgnorePatterns and the package’s published format. Capacitor plugins can expose this problem when Jest ignores a dependency that still needs transformation. Jest’s newer releases have improved startup and memory behavior, but watch feedback can still trail ESM-focused alternatives in large projects (Capacitorのライブアップデートの代替手段は、以下の点で異なります。A setup file can provide controlled shims without pretending that Jest is a real device or desktop shell: experimentalVMModules If an ESM-only dependency fails during collection, inspect and the package’s published format. __CAPGO_KEEP_0__ plugins can expose this problem when Jest ignores a dependency that still needs transformation. Jest’s newer releases have improved startup and memory behavior, but watch feedback can still trail ESM-focused alternatives in large projects (2026 Jest and Vitest comparison). Treat as a compatibility lever to test deliberately, not a default switch.
JavaScriptに焦点を当てたセットアップウォークスルー用に使用します。 CapgoのJavaScriptのユニットテストガイドを使用します。.実際の検証コマンドでインストールを完了します:
npx jest --runInBand
Smokeテストがパスすると、Jestがプロジェクトを読み込むことが確認されます。ただし、生産モジュールとテストモジュールのグラフが同一であることを確認するわけではありません。したがって、ESM、DOM、プラグインのインポートテストを、パスが関係する場合に実行してください。
最初の信頼できるユニットテストを書く
有用なユニットテストは、制御されたコンテキストで観察可能な動作を説明します。 アレンジ、実行、確認 パターンは、その意図を明確にします:入力と依存関係を準備し、公開された関数を呼び出し、結果または外部に可視化される影響を検証します。
請求書モジュールがこの関数をエクスポートしている場合、
export function calculateInvoiceTotal(
subtotal: number,
taxRate: number,
discountRate: number,
): number {
const discounted = subtotal * (1 - discountRate)
return Math.round(discounted * (1 + taxRate) * 100) / 100
}
テストは財務的な動作に焦点を当て、ローカル変数名 discounted:
import { calculateInvoiceTotal } from './calculateInvoiceTotal'
describe('calculateInvoiceTotal', () => {
it('applies percentage discount before tax', () => {
const subtotal = 100
const taxRate = 0.2
const discountRate = 0.1
const total = calculateInvoiceTotal(subtotal, taxRate, discountRate)
expect(total).toBe(108)
})
it('rounds the final amount to currency precision', () => {
const total = calculateInvoiceTotal(19.99, 0.2, 0)
expect(total).toBe(23.99)
})
})
それぞれの動作を表します。後でリファクタリングが内部計算を変更した場合でも、契約を維持する限り、これらのテストは有用なままです。 it __CAPGO_KEEP_0__

非同期テストも同じ規律が必要です。Capgoの resolves と rejects 期待されるプロミス結果を明示的にします:
it('returns an invoice from the API', async () => {
await expect(fetchInvoice('invoice-123')).resolves.toMatchObject({
id: 'invoice-123',
})
})
it('rejects when the invoice is missing', async () => {
await expect(fetchInvoice('missing')).rejects.toThrow('Invoice not found')
})
危険な間違いは、期待値を拒否したり、待たずに返したりすることです。Jestに焦点を当てたガイダンスは、忘れられた await または return 信頼性の高いユニットテストの書き方のための4つの基本ステップを示すリストグラフィック。非同期テストも同じ規律が必要です。Capgoのと
期待されるプロミス結果を明示的にします:
- 危険な間違いは、期待値を拒否したり、待たずに返したりすることです。Jestに焦点を当てたガイダンスは、忘れられた ステートメントは、偽陽性の原因となり、明確な警告なしにテストが通過する原因となります(」Jestユニットテストの慣行」)。「テストは、失敗パスを検証していないため、待たずにアサーションを実行していないテストです。
- 内部状態の確認: 戻り値、発行されたイベント、永続化されたレコード、または可視な出力を優先してください。
- 呼び出し確認を過度に使用する:
toHaveBeenCalled()単独ではあまり意味がありません。関連する引数と結果の動作を確認してください。
PR チェックリストは短く残すことができます:
- 各テストが 1 つの動作をカバーしているかどうか?
- テストは Arrange、Act、Assert の順に進んでいるか?
- 非同期の期待値は待機されているか?
- 依存関係は明確な境界でモックされているか?
- テストは内部のリファクタリングに耐えられるか?
コンポーネント固有の例の場合 CapgoのReactユニットテストガイド 同様の動作原則をレンダリング出力とユーザー向けのインタラクションに適用します。
実際にスケールするモック戦略
モッキングが困難になるのは、スイートが大きくなる時です。短絡が作成するメンテナンス義務は、すべて。手書きの jest.fn() can be exactly right for a callback. A module replacement can isolate an SDK. A network interceptor can preserve more of the application’s real request behavior. The choice should follow the seam you’re testing.
Consider a payment validator that calls a Stripe SDK, records an audit event, and reaches an HTTP risk service. A focused unit test might spy on the logger, replace the payment SDK, and intercept the risk request. Each technique controls a different boundary.
| の実際の要求動作の多くを保存できます。選択は、テストするシームに従うべきです。 | 考慮すべきは、Stripe | を呼び出す支払い検証者、 | を記録するアドビットイベント、 | に到達するHTTPリスクサービスです。集中したユニットテストでは、 |
|---|---|---|---|---|
jest.fn() をスパイするか、 jest.spyOn() |
を置き換え、リスク要求をインターセプトするか、各テクニックは異なる境界を制御します。 | 集中 | ローカル時は低 | コールバック、ロガー、インジェクトサービス |
jest.mock() |
中 | 低から中 | 急激に成長する | 高コストのサイドエフェクトを持つSDK、モジュール |
| MSW | 中 | HTTP境界で高 | 集中化 | リクエストの振る舞い、エラー、レスポンス契約 |
ローカル決定用の手動スパイ
依存性がすでにインジェクションされている場合、テストが 1 つのインタラクションを観察または制御する必要がある場合にスパイを使用してください:
const audit = {
record: jest.fn(),
}
const result = await validatePayment(input, {
paymentClient,
audit,
})
expect(audit.record).toHaveBeenCalledWith(
expect.objectContaining({ event: 'payment.validated' }),
)
expect(result.status).toBe('approved')
ケース間で状態をリセットする。共有状態は Jest の失敗の原因となることが多く、ガイドラインではモッククリアリングを組み合わせて呼び出し数と状態の漏洩を防止することを推奨しています ( beforeEach Jest 単体テストのマスター重量級の SDK のモジュールモック).
Stripe またはネイティブ プラグイン モジュールは、ロードしたときにすぐにセットアップを実行します。生産実装をロードする場合に、資格情報、ネイティブ バインディング、または無関係な動作を導入することは避けます:
アプリケーションから返された値を確認するようにテストを実行してください。意味のある結果がなくても、モックが設定されたことを証明するだけのパッシング __CAPGO_KEEP_0__ 呼び出しアサーションは、実際には何も証明しません。
jest.mock('stripe', () => ({
payments: {
authorize: jest.fn(),
},
}))
The test should still assert the value returned by the application. A passing SDK call assertion without a meaningful result can prove only that the mock was configured.
__CAPGO_KEEP_0__ がリクエストの構築、レスポンスのパース、リトライ、エラーの翻訳を所有している場合、MSW は HTTP 層をキャッチしながらリクエストのパスを保存できます:
For code that owns request construction, response parsing, retries, or error translation, MSW can intercept the HTTP layer while preserving the request path:
server.use(
http.post('/risk/check', async () => {
return HttpResponse.json({ decision: 'review' })
}),
)
低レベルの呼び出しを毎回モックするよりも信頼性が高くなります。また、Node とブラウザのような環境でレスポンスシナリオを名付け・再利用することも容易になります。 fetch MSW は HTTP 層をキャッチしながらリクエストのパスを保存できます:
モックはセームではなくセーム自体に
オーバーモッキングは、統合のワイヤリングが破綻している場合にテストが通過するテストを生み出し、実際のネットワーク、ファイルシステム、クロック、またはデータベースをユニットテストに取り込むと、遅く、非決定論的なスイートを生み出す。純粋な論理をすべてのI/Oから解放し、境界の検証を契約または統合テストに移動し、インターフェイスが重要である場合に。
JestをCIとカバレッジゲートと統合する
CIは2つの異なる質問に答えるべきです。最初は、高速なユニットスイートが安全な変更を拒否するかどうか。2番目は、重要な境界がまだ機能するかどうかを確認するために、遅い統合チェックを実行するか。すべてのテストを1つの統一されたコマンドにすると、フィードバックを解釈するのが難しくなり、開発者がスイートを回避するようになる。
Nodeランタイムを固定するGitHubアクションワークフローは、依存関係のキャッシュにロックファイルを使用し、JestのCIモードでユニットチェックを実行できます。
name: test
on:
pull_request:
push:
jobs:
unit:
runs-on: ubuntu-latest
strategy:
matrix:
node: [20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: npm
cache-dependency-path: package-lock.json
- run: npm ci
- run: npm run test:unit, --ci --coverage
- uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.node }}
path: coverage/
パッケージスクリプトは、高速テストと統合ワークを分離できます。
{
"scripts": {
"test:unit": "jest --runInBand tests/unit",
"test:integration": "jest --runInBand tests/integration"
}
}
カバレッジの閾値をリスクに基づいて設定するのではなく、習慣的に選択した固有の数字を選択するのではなく。
module.exports = {
collectCoverageFrom: ['src/**/*.{js,ts,tsx}'],
coverageThreshold: {
global: {
branches: 70,
functions: 80,
lines: 80,
statements: 80
}
}
}
これらの値は、設定の例であり、業界標準として検証されていないものです。実際のフロアをリポジトリの現在のベースラインから設定し、チームが意味のあるカバレッジを追加するたびに、それを引き上げることができます。厳格なゲートは、生成されたものや低リスクのcodeを測定する場合に、緊急修正をブロックする可能性があります。緩いゲートは、重要なパスが気づかれずに劣化する可能性があります。

大規模リポジトリの場合、テスト分離が確実な後で、行列ベースのシャーディングを使用してください。各シャードには、レポートの明確な所有権が必要であり、最終的なステータスは、Pull Requestに失敗を表示するのではなく、ログに埋め込まないようにしてください。チームは、サービスがレポートを正しくマージするように設定されている場合、CodecovまたはCoverallsにHTMLカバレッジをアップロードし、公開することもできます。 lcov データをCodecovまたはCoverallsにアップロードし、公開するには、サービスがレポートを正しくマージするように設定されている必要があります。
読む CIの運用慣行 alongside your workflow design, especially if multiple applications share one repository. Capgo’s 大規模なJestスイートは、常にパスすることができますが、間違ったことをテストしている場合。テストが実装詳細に依存している場合、スナップショットが有効なレビューの範囲を超えている場合、または共有モックがテストが設定したものとは異なる動作を示している場合、信頼性が低下します。 スナップショットには意図的な所有権が必要です。構造が実際の契約である場合、たとえば安定したコンポーネントまたはシリアライズされたメッセージの場合、スナップショットは効果的です。開発者が出力の検査を行わずに広範な更新を承認すると、ノイズが生じます。意図的に再生成し、差分をレビューし、意味のある動作を保護しないファイルを削除してください。
レイヤーを使用するのではなく、Jestがすべてを所有する必要性を強制しない
各テストレイヤーには、狭いジョブが必要です:
信頼性のあるJestユニットテストを大規模に保つ
信頼性のあるJestユニットテストを大規模に保つ
信頼性のあるJestユニットテストを大規模に保つ
- 単体テスト: ネットワークやファイルシステムへのアクセスなしで、決定論的計算、パーサー、削減子、ポリシー決定、エラーのマッピングを検証します。
- 契約テスト: モジュールの境界、エディタの形状、リクエストのペイロード、プラグイン向けの動作を確認します。
- 薄いE2Eカバレッジ: Web、Capacitor、またはElectronシェル上で、実際のユーザージャーニーを少数実行します。
この配置では、単体テストを高速化しながら、モックが生産的な境界を表現することができなくなる場所をチェックします。さらに、モバイルの一般的な失敗モードを回避します: 高価なUIパスを通して、すべてのネイティブのアップデートやパーミッションフローをテストするのではなく、JavaScriptの決定論的ロジックを分離します。
1つの動作ごとに it() なので、失敗は診断可能です。呼び出し順序をアサートするのは、契約に属する場合のみです。クエリ可能なフェイク、たとえばメモリ内リポジトリとメソッドが保存されたレコードを公開するものは、ハードコードされた戻り値が現在の実装をコピーするだけの場合よりも、より良いフィードバックを提供します。
パスするテストは、ユーザーや隣接するモジュールが依存できることを説明するべきであり、今日のcodeがどのように構成されているかを説明するべきではありません。
定期的なテストヘルスレビューをスケジュールします。フレイキーテスト、古いスナップショット、冗長なセットアップ、モックが生産的な動作と一致しない場合を確認します。低価値のテストを削除することは、すでに隠蔽が多すぎるテストに別のアサーションを追加することよりも安全です。
CI ダッシュボードでフラッキネスを追跡する。テストが失敗した場合に code の変更がない場合は、失敗の証拠を保存し、共有状態を分離し、時間とランダム性を制御し、ワーカーの負荷を減らして、ランナーがオーバーロードされている場合にワーカーの設定を制限する。CI マシン上の測定値に基づいてワーカーの設定を設定し、追加の並行性が競合を増やし、スイートの速度を下げる可能性があるため。ワーカーの設定をランナー設定とともにドキュメント化して、将来の変更が意図的なものになるようにする。
チームのための決定枠組みと次のステップ
Jest は、リポジトリがすでに安定したスイート、established トランスフォーム、モック、チームがランナー実験よりもマイグレーション安全性を優先する場合、信頼できるデフォルトです。新しいプロジェクトが ESM-ファースト、ネイティブフィードバックが優先される、または watch-mode の再実行が開発を頻繁に妨げる場合に、代替品を比較することを検討してください。リポジトリのアーキテクチャとトランスフォーマーの作業に応じて、公開された比較結果は大きく異なる可能性があるため、方向性として扱ってください。
4 つの基準を使用します。
- 既存のツール: Jest を維持するには、既存の設定、テストユーティリティ、CI の慣習が機能していることを確認する。
- モジュール形式: ESM-オンリー依存関係が繰り返し例外またはカスタムワークアラウンドを必要とする場合、ランナーを再検討する。
- フィードバックの期待: 実際のリポジトリで代表的な watch 変更を測定する。空のデモプロジェクトではありません。
- チームの能力: チームが設定およびデバッグできる熟練したランナーが、高速なツールを適切に使用していない場合に、より良い結果を生み出す可能性があります。
Vitest、Nodeの組み込みテストランナー、Playwrightは異なるニーズを対処します。Playwrightは主にブラウザのE2Eカバレッジに適しています。Nodeのランナーは、焦点を当てたNodeサービスに適しています。Vitestはよくあるケースでは、greenfield ESMとVite向けのプロジェクトに適しています。Jestは、成熟したモック、変換、既存のCI規約に依存するチームに適しています。信頼できる境界を維持しながら、フィードバックが利用可能なものにします。
実践的な90日間のリセット
第1月、スイートを検査します。 所有者を割り当てて、フラッキーテスト、死んだスナップショット、実装に結びついたアサーション、実際のI/Oを実行するテストをカタログ化します。出力は、削除、修理、統合カバレッジが必要な境界の書かれたリストでなければなりません。
第2月、設計を標準化します。 共有テストユーティリティを追加し、モッキング規約をドキュメント化し、重要なパッケージのカバレッジレポートを導入します。ゲートが設定されているパッケージと、焦点が当てたテストが不足している動作を記録し、基準がレビュー可能なものにします。
第3月、配信を安定させます。 CIワーカーを調整し、単位と統合ジョブを分離し、リスクベースのカバレッジフロアを設定し、規約をドキュメント化します。パイプラインは、実行可能な失敗を報告し、新しいテストは同じ境界とモッキング規約に従うものにします。 TESTING.md第3月、配信を安定させます。
定期スケジュールでスイートをレビュー。古いスナップショット、冗長なセットアップ、モックを削除して、生産環境の動作に一致しなくなったもの。低価値のテストは、もう一つのアサーションで強化するのではなく、削除することの方が安全かもしれません。CIでフレイキーな失敗を追跡し、証拠を保存し、共有状態を分離し、時間とランダム性を制御し、競合が発生したときにワーカーの圧力を減らしてください。CIマシンでの測定値に基づいてワーカーの制限を設定し、ランナー構成と共にドキュメントを保存してください。
これらの慣習は、より広範な ソフトウェア開発のベストプラクティス. For a tested JavaScript fix targeting Capacitor or Electron users, Capgo can deliver signed JavaScript, CSS, configuration, and asset bundles through targeted channels, with rollback protection and release observability, without requiring a store review for every web-layer correction.
If your team ships Capacitor or Electron applications, visit Capgo to assess how live JavaScript updates fit controlled channels, staged rollouts, and rollback protection. Start by documenting Jest boundaries and CI gates, then define where Capgo belongs in the recovery path for fixes that need prompt delivery.