bun
Unit Tests JavaScript: Comprehensive 2026 Guide Capacitor そして Electron アプリケーション。 シンプルな機能は、共有ビジネスロジック、ブラウザAPI、ネイティブプラグイン、ローカルファイル、IPC、リモートサービスと同じフローで触れることができます。 それらの部分を間違った方法でテストすると、スイートは偽の依存関係の迷路になります。 それらを正しい方法でテストすると、破綻するロジックに対して迅速なフィードバックが得られます。
良いユニットテストは、JavaScriptの作業は、巧妙なマッチャーシntaxから始まらない。 それが、厳格な境界から始まる:純粋なロジックを直接テストし、副作用を分離し、内部関数をリネームすると同時にテストを書かないようにする。
目次
- JavaScriptテストフレームワークを選択する
- プロジェクトの設定と最初のテスト
- 非同期Codeとアynchronousをマスターする
- 強力なテストのための高度な戦略
- CI、Capacitor、およびElectronアプリのテスト
- JavaScript単体テストに関するよくある質問
JavaScriptテストフレームワークの選択
プロフェッショナルなJavaScriptプロジェクトには、実際のテストランナーが必要です。アドホックスクリプトとマニュアルコンソールチェックは、複数のエンジニアが同じコードベースに触れるとスケールしなくなります。テストの発見、断言、非同期処理、モック、CIとローカル開発で一貫して実行する方法が必要です。
現在のガイドラインは、主流のオプションに収束しています。 Jest、Mocha、Jasmine は、主なフレームワークとして繰り返し強調されています。 Jest __CAPGO_KEEP_0__は、組み込みテスト構造、断言、モッキング、非同期サポートを一つのパッケージで提供するため、よく単独で取り上げられる PluralsightのJavaScriptテストラボ.

フレームワークは必須
チームが最初に犯す間違いは、ユニットテストを副次的な活動として扱うことです。通常、これは不一致のファイル名、誰も覚えていないカスタム断言、そして誰もが理解できないヘルパーに至ります。
フレームワークは共通言語を提供します。
- テスト構造 with
describeandtestorit - 断言 with readable matchers
- Hooks セットアップと解放のために
- 非同期サポート プロミスとタイマーのために
- 外部依存性のためのモッキングツール あなたのチームも、ユニットレベルの作業を超えたテスト自動化のより広い視点が必要な場合、__CAPGO_KEEP_0__ はアプリ配信ワークフローの自動テストについて便利な概要を提供しています。
If your team also needs a broader view of test automation beyond unit-level work, Capgo has a useful overview of JestとMochaは、異なる哲学を表しています。.
Jest
は、初日にはチームが必要とするほとんどのものを含むオールインワンオプションです。
Jest は、初日にはチームが必要とするほとんどのものを含むオールインワンオプションです。
Mocha __CAPGO_KEEP_0__はモジュラーです。ランナーを提供し、残りのスタックを組み立てることを期待します。
| 機能 | Jest | Mocha |
|---|---|---|
| セットアップの複雑さ | 多くのチームでは低くなります | 通常、アサーションとモッキングライブラリを追加するため、高くなります |
| アサーション | 組み込まれている | 通常、別のライブラリと組み合わせて使用します |
| モッキング | Built in | 通常は他のライブラリと組み合わせて使用される |
| 非同期テスト | Built inと直感的 | サポートされているが、周囲の設定に依存する |
| カバレッジ ワークフロー | よく同じツールチェーンに組み込まれる | 多くの部分が組み合わせられている |
| 最も適した選択 | 新規プロジェクト、統一性を求めるチーム | 既存のスタック、モジュラー制御を求めるチーム |
実用的なルール: チームが、ランナーと組み合わせるべきアサーションライブラリとモッキングライブラリを判断する必要がある場合、Jestを使用したいと思います。
私が大多数のチームに推奨するもの
大多数の現代的なプロジェクトでは、Jestを選択することをお勧めします。 Mochaを使用しているコードベースがすでにある場合は除きます。 アプリケーションが Capacitor または Electronを含む場合、Mochaを使用する理由はさらに強くなります。
Mochaは、既存のエコシステムがすでに確立されている古いNode.jsサービスまたは長期間にわたるコードベースではまだ意味があります。
しかし、mid-levelエンジニアがスクラッチから強力なセットを設定する場合、Jestは通常、より多くのフリクションを削減します。
重要な範囲の注記。CypressとPlaywrightは優れたツールですが、異なる問題を解決します。ブラウザレベルとエンドツーエンドのチェックに適していますが、ユニットテストのJavaScriptの内部ループではありません。
A clean testing setup should be boring. If adding the first test feels complicated, the suite probably won’t stay healthy.

A simple Jest setup
最初にJestを開発依存モジュールとして追加し、テストスクリプトを設定するJavaScriptプロジェクトから始めましょう。 package.jsonそれだけが多くのプロジェクトにとって十分です。モジュールシステム、トランスピラーション、またはモノレポ構造がそれを必要とする場合、追加の設定を後で追加できます。
{
"scripts": {
"test": "jest"
}
}
ローカルで__CAPGO_KEEP_0__アプリを構築している場合、共有ロジックの周りでテストを追加する前に開発環境を整理したい場合は、__CAPGO_KEEP_1__の
If you’re building a Capacitor app locally and want your dev environment in order before adding tests around shared logic, Capgo’s guide to setting up a Capacitor local environment テストを書く前に__CAPGO_KEEP_0__
テストを書く前にcode
テストを書く前に__CAPGO_KEEP_0__ テストを書く前に__CAPGO_KEEP_0__テストを組織する describe と it、 expect(...) 、 の確認を枠組みにした.
That matters because test-first changes how you design code. Functions tend to become smaller, dependencies become more visible, and side effects stop leaking into logic that should stay pure.
それが重要なのは、テストから始めることで設計が変わるからです。
// math.js
function addTax(amount, rate) {
return amount + amount * rate;
}
module.exports = { addTax };
// math.test.js
const { addTax } = require('./math');
describe('addTax', () => {
it('returns the amount with the tax applied', () => {
expect(addTax(100, 0.2)).toBe(120);
});
});
機能は小さくなる、依存関係は明確になり、副作用は純粋でなければならないロジックに漏れ込むのを止めることができるからです。
ここに最小限の例があります。 Arrange Act Assertを毎回使ってください。 の
- Arrange, Act, Assertのパターンは、テストが複雑になるにつれても、読みやすくすることができます。 targetLanguage":"Japanese","protectedTokens":["Cloudflare","Capacitor","GitHub","Capgo","code","API","SDK","CLI","npm","bun"],"texts":["入力データと必要なセットアップを含めてください。",
- Act ,
- Assert on the outcome.
Applied to a validation helper:
function isSupportedPlatform(platform) {
return ['ios', 'android', 'web', 'desktop'].includes(platform);
}
describe('isSupportedPlatform', () => {
it('returns true for ios', () => {
// Arrange
const platform = 'ios';
// Act
const result = isSupportedPlatform(platform);
// Assert
expect(result).toBe(true);
});
});
Small tests age well. A test should usually answer one question, not narrate an entire workflow.
For Capacitor and Electron projects, that discipline matters more because your pure logic often sits next to native or desktop integration code. Keep the business rule testable without the platform runtime, and your first test won’t be your last useful one.
Mastering Mocks and Asynchronous Code
Most bugs in application code don’t come from adding two numbers. They come from code that reaches outside itself: network requests, files, plugin APIs, timers, IPC channels, storage layers.
That’s where mocking helps. It gives you control over the boundary so the test can focus on your code’s decision-making.

モック境界を設定せずにすべて
保守可能なテストガイドは 単一の動作カバレッジ そして テストごとに1つの強力なアサーション, そして、モックを過度に使用すると、テストが実装の詳細に密接に結びつき、脆弱になることも警告しています。これは、 TestRailの保守可能なユニットテストに関する記事.
その警告は、JavaScriptで非常に重要です。チームは、すべてのインポートされたモジュールをモックすることから始め、実際の動作をテストするのではなく、関数が他の関数を「正しく」呼び出すかどうかをテストするのではなく、機能をテストするのではなく、関数が他の関数を「正しく」呼び出すかどうかをテストするのではなく、
モックが多すぎるテストの悪い目標:
- ヘルパーAがヘルパーBを呼び出したかどうか
- サービスCがシリアライザーDを呼び出したかどうか
- 内部プライベート関数が2回実行されたかどうか
より良い対象:
- __CAPGO_KEEP_0__が返した値
- __CAPGO_KEEP_0__が依存関係のエラーを正しく処理したか
- __CAPGO_KEEP_0__がデータを期待どおりに変換したか
CapacitorとElectron codeのためのより良いパターン
モバイルとデスクトップアプリでは、ネイティブまたはプラットフォームAPIのラッパー層を好みます。次に、ユニットテストはラッパーをモックし、プラットフォーム自体をモックしません。
例の構造:
// cameraGateway.js
async function getPhoto(cameraPlugin) {
return cameraPlugin.getPhoto();
}
module.exports = { getPhoto };
// profilePhotoService.js
async function loadProfilePhoto(cameraGateway) {
const photo = await cameraGateway.getPhoto();
return { path: photo.path, ready: true };
}
module.exports = { loadProfilePhoto };
// profilePhotoService.test.js
const { loadProfilePhoto } = require('./profilePhotoService');
test('returns mapped photo data', async () => {
const fakeCameraGateway = {
getPhoto: jest.fn().mockResolvedValue({ path: '/tmp/pic.jpg' })
};
const result = await loadProfilePhoto(fakeCameraGateway);
expect(result).toEqual({ path: '/tmp/pic.jpg', ready: true });
});
Electronでもそのパターンが機能します。Wrap ipcRendererファイルアクセス、またはシェル統合を薄いアダプターの後ろにします。ユニットテストはサービス層に当たりますが、直接実行環境に当たりません。
Capacitorアプリのリリースロジックとアップデートパスをテストするチーム向けに、Capgoは CapacitorのOTAアップデートをモックシナリオでテストするためのガイド.
アシンクロニズドテストスタイルを正常化するチームのために、迅速なウォークスルーが役立ちます:
非同期フローを不安定性なくテストする
テストで async/await in tests when the code under test returns a promise. It’s clearer than callback-heavy patterns and easier to debug.
async function fetchProfile(api) {
const response = await api.getUser();
return response.name;
}
test('returns the user name from the API response', async () => {
const api = {
getUser: jest.fn().mockResolvedValue({ name: 'Ava' })
};
const result = await fetchProfile(api);
expect(result).toBe('Ava');
});
__CAPGO_KEEP_0__
test('throws when the API request fails', async () => {
const api = {
getUser: jest.fn().mockRejectedValue(new Error('network failed'))
};
await expect(fetchProfile(api)).rejects.toThrow('network failed');
});
がPromiseを返す場合に使用します。コールバックが多く含まれるパタームよりも明確で、デバッグも容易です。
失敗パスもテストする
A test suite becomes useful when it stays useful after the code changes. That’s harder than writing a pile of passing tests.

テストスイートは、
__CAPGO_KEEP_0__ 70/20/10 が変更された後でも有用なままになることが重要です。単にパスするテストを大量に書くことよりも難しいです。 堅牢なソフトウェアを構築するための包括的なテストカバレッジと維持可能なテストスイートの図示, 単位テストで最速のフィードバックと最安定なエラーを提供するように指示されています。同様のガイドでは、完全な単位スイートは理想的には 10 秒以内に完了し、pre-commit チェックは 5 秒以内に完了するようにすることを推奨しています。 この OpenReplay テストガイドに従っています。私はそれを予算ツールとしてではなく、宗教として捉えていません。エンドツーエンドテストに多くの努力を費やした場合、チームはフィードバックを得るのに長い時間を待つことになります。単位テストのみに焦点を当てた場合、システムの境界を実際に無視することになります。 Capgo または Electron アプリの場合、健康的なバランスは通常以下のようになります。単位テスト 価格ロジック、許可ルール、シリアライズ、更新の有効性、機能フラグ、状態変換のテスト.
統合テスト
For a Capacitor or Electron app, a healthy balance usually looks like this:
- budgeting tool system boundaries
- pricing logic permissions rules
- エンドツーエンドテスト ログイン、購入フロー、同期、または更新ポップアップなどの重要なジャーニーに対して数回実行する
カバレッジはランプではなく目標
カバレッジレポートは、重要なロジックの未テストのbranchを発見するのに役立つ場合に有用ですが、チームがカバレッジパーセンテージを追求するためにそれ自体で有用な場合には有害です。
ログインバリデーターに思いやりのあるエッジケーステストを実行すると、重要なUIのバリデーションを強化するチームにとって、重要なロジックのカバレッジが高いファイルに多くのトリビアルアサーションが含まれるよりも価値があります。特に、フォーム、パーサー、日付ロジック、パーミッションチェックなどの入力が多いcodeに対してはそうです。チームがバリデーションヘビーUIの品質を強化している場合、この フロントエンドフォームバリデーションをマスターする のガイドは、ユニットレベルテスト戦略の補完として役立ちます。
振る舞いベースのテストはリファクタリングに耐える
信頼できるスイートは、内部のリファクタリングを行うとテストの半分を書き直さなければならないことなく、リファクタリングを実行できるようにする最も簡単な方法は、実装詳細ではなく 観察可能な振る舞い をアサートすることです。
ユースケースがよく通用するもの:
- 境界条件 __CAPGO_KEEP_0__の入力値が空、null値、無効なデータ型、文字列が大きすぎる場合など
- ドメインの結果 権限が欠如しているため返却が拒否された場合など
- 状態の移行 メタデータの検証が完了した後、ダウンロードをマークする
よく使われていない用途
- 内部ヘルパー関数を調べる
- プライベートメソッドのシーケンスを確認する
- 呼び出しチェーンのすべての層をモックする
アプリ開発チームが厳格なリリースプロセスを構築している場合、Capgoの記事 __CAPGO_KEEP_0__のアプリケーション品質保証 は、テスト作業をより広いリリースパイプラインに接続することで、有用である。
CI、Capacitor、およびElectronアプリのテスト
1人の開発者のマシン上で実行されるテストだけでは、安全ネットではありません。ローカルな習慣です。
CI turns unit tests JavaScript work into team infrastructure. Every push, pull request, or release branch can exercise the same commands with the same expectations. That consistency matters even more for Capacitor and Electron projects, where environment drift causes subtle failures.
この一貫性は、環境の変化が微妙なエラーを引き起こす__CAPGO_KEEP_0__およびElectronプロジェクトにとって、もっとも重要です。
CIをデフォルトの実行パスに設定する
A basic GitHub Actions workflow can be as small as this:
name: test
on: [push, pull_request]
jobs:
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
__CAPGO_KEEP_0__アクションの基本的なワークフローは、以下のようになります。
For mobile teams shipping through automated pipelines, Capgo has a practical guide to 自動化されたパイプラインを通じてモバイルチームが配信する場合、Capacitorには、CapacitorアプリのCI/CDの設定方法の実用ガイドがあります。.
Capacitorプラグインの相互作用をテストする
ユニットテストのCapacitorcodeの間違った方法は、プラットフォームブリッジに直接nativeプラグインをすべてのサービスにpullすることです。
より良いパターンは、薄い抽象化です:
// deviceStorage.js
async function saveFile(filesystem, path, data) {
return filesystem.writeFile({ path, data });
}
module.exports = { saveFile };
// draftService.js
async function persistDraft(storage, draft) {
await storage.save('draft.json', JSON.stringify(draft));
return { saved: true };
}
module.exports = { persistDraft };
// draftService.test.js
const { persistDraft } = require('./draftService');
test('persists a serialized draft', async () => {
const storage = {
save: jest.fn().mockResolvedValue(undefined)
};
const result = await persistDraft(storage, { title: 'Hello' });
expect(result).toEqual({ saved: true });
});
カメラアクセス、バイオメトリックのプロンプト、プッシュトークンの登録、ネットワークのステータスについても同じ考え方が当てはまります。アダプター内でプラグインの呼び出しを維持し、コントロールするインターフェイスでアプリのロジックをテストしてください。
ElectronのメインレンダラーとIPCのテストcode
Electronアプリには2つの重要なシームがあります: メインプロセスcode と レンダラー プロセスcode。テストではぼかさないでください。
信頼できるセットアップは通常、以下を分離します:
- ビュー モデルのユニット テスト ビュー モデル、状態、フォーマット、UI側のビジネス ロジック
- メイン プロセスのユニット テスト for menus、ファイル操作、そしてアプリライフサイクル決定
- IPC契約テスト for メッセージ形状と期待される応答
Example IPC wrapper:
// ipcGateway.js
function sendSettings(ipcRenderer, payload) {
ipcRenderer.send('settings:update', payload);
}
module.exports = { sendSettings };
// ipcGateway.test.js
const { sendSettings } = require('./ipcGateway');
test('sends settings update over ipc', () => {
const ipcRenderer = { send: jest.fn() };
sendSettings(ipcRenderer, { theme: 'dark' });
expect(ipcRenderer.send).toHaveBeenCalledWith('settings:update', { theme: 'dark' });
});
If you later change the internal implementation from one helper to another, this test still holds because it verifies the behavior that matters. That’s the standard you want across desktop and mobile code.
よくある質問:JavaScript単体テスト
単体テストと統合テスト、E2Eテストの違い
A 単体テスト 1つの小さなロジックの単体テスト。 統合テスト 複数のコンポーネントまたはサービスが正しく機能するかどうかを確認する。 end-to-endテスト 実行中のアプリケーションを通してユーザージャーニーをテストする。
単位テストを使用してビジネスルールに対する迅速な信頼を確立する。統合テストを使用してストレージ、プラグインラッパー、IPCなどのシームをテストする。E2Eテストを慎重に使用して、破綻すると大きなダメージを受けるワークフローをテストする。
完全なカバレッジを目指すべきか
いいえ。完全なカバレッジはチームを低価値のテストに導く。
カバレッジは、誰も実行していないリスクのあるcodeを明らかにするときに役立つ。エンジニアがダッシュボードを満たすために浅いアサーションを追加するだけのときは役に立たない。スイートが脆い場合、カバレッジがそれを救うことはない。
既存のコードベースにテストを追加する方法はありますか
変更がすでに発生している場所から始める。テスト戦略の大きなリライトを発表してチームを凍らせないでください。
実践的なシーケンスは次のようになります。
- アクティブなcodeを保護する 機能開発またはバグ修正の際に変更するモジュールにテストを追加する
- 純粋なロジックを抽出する 難テストファイルからビジネスルールをテストできるようにするため、フレームワークや実行環境のノイズが混入しないようにする
- セームWrappersを追加する ネイティブプラグイン、ネットワーククライアント、ファイルシステム呼び出し、Electron IPC周り
- 脆弱なパターンを拒否する モックを導入する際に生じる、過度にモックしたり、脆弱なテストが続く問題を指摘する JavaScriptテストベストプラクティス 特に、過度にモックしたり、脆弱なテストが続く問題を指摘することが難しいことが多いので、ここでは特に有効
目標は即時的な完全性ではなく、チームが最もコストがかかる場所でリグレッションが発生するのを防ぐための、安定した改善
チームが Capacitor または Electron JavaScriptの変更に対しては、よりきれいなリリースプロセスが必要です。 Capgo CapacitorJSおよびElectronアプリのライブ更新を提供し、ロールアウト制御と観察性を備えたCapacitorJSとElectronアプリのライブ更新を提供するため、チームは、ウェブバンドルの変更をストアのレビュー待ちなしで安全に配信できるようにすることができます。