__CAPGO_KEEP_0__のホーム

Unit Tests JavaScript: 2026年版徹底ガイド

Master unit tests javascript with our 2026 guide. Covers Jest, Mocha, setup, mocking, CI, and tips for Capacitor & Electron apps.

Unit Tests JavaScript: 2026年版徹底ガイド

あなたは現在、2つの状況のいずれかにいるかもしれません。JavaScriptプロジェクトがほとんどテストがなく、リファクタリングがリスクが高く感じる場合、またはすでにテストがあって半分以上が遅い、脆弱で、信頼できないものである場合

状況は CapacitorElectron アプリケーション。単純な機能は、共有のビジネスロジック、ブラウザAPI、ネイティブプラグイン、ローカルファイル、IPC、リモートサービスと同じフローで触れます。間違った方法でそれらをテストすると、スイートは偽の依存関係の迷路になります。正しい方法でテストすると、論理が壊れるときに迅速なフィードバックが得られます。

JavaScriptの単位テストは、賢いマッチャーシntaxで始まるのではなく、規則正しい境界で始まります。純粋なロジックを直接テストし、副作用を分離し、内部関数をリネームするとテストが崩れることを避けます。

目次

JavaScriptのテストフレームワークを選択する

プロフェッショナルなJavaScriptプロジェクトには、実際のテストランナーが必要です。アドホックのスクリプトと手動のコンソールチェックは、複数のエンジニアが同じコードベースに触れると、スケールしなくなります。テストの発見、断言、非同期処理、モック、CIとローカル開発ですべてを一貫して実行する方法が必要です。

現在のガイドラインは、主流のオプションに収束しています。 Jest、Mocha、Jasmine は、主なフレームワークとして繰り返し強調されています。 Jest 単一テストの構造、断言、モッキング、非同期サポートがすべて一つのパッケージで提供されていることを示すものとしてよく単一テストの構造を単に単一テストの構造と呼ぶことが多い。 PluralsightのJavaScriptテストラボ.

JavaScriptテストフレームワークの比較チャート、Jest、Mocha、Cypress、Playwrightなどを含む。

フレームワークは必須

チームが最初に犯す間違いは、単一テストを副次的な活動として扱うことである。 これは、不一致のファイル名、誰も覚えていないカスタム断言、誰も理解できないヘルパーに至るまで、通常の結果である。

フレームワークは共通の言語を提供する

  • テストの構造 そして describe または test 断言 it
  • 読みやすいマッチャー with
  • Hook セットアップと解放のための
  • 非同期サポート プロミスとタイマーのための
  • 外部依存性のためのモックツール あなたのチームも、単位レベルの作業を超えたテスト自動化のより広い視点が必要な場合、__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

すべての機能が含まれているオールインワンオプションです。

day one Jestは、ほとんどのチームが最初の日から必要なものが含まれています。
Mocha はモジュラーです。ランナーを提供し、残りのスタックを組み立てるように求めます。

機能 Jest Mocha
セットアップの複雑さ ほとんどのチームでは低い 通常はアサーションとモッキングライブラリを追加するため
アサーション 組み込まれている 通常は別のライブラリと組み合わせて使用する
モッキング 組み込まれた機能 通常は別のライブラリと組み合わせて使用
非同期テスト 組み込まれた機能で直感的 サポートされているが、周囲の設定に依存する
カバレッジワークフロー よく同じツールチェーンに統合される よく組み立てられる
__CAPGO_KEEP_0__ 新規プロジェクト、統一性を求めるチーム 既存のスタック、モジュラー制御を求めるチーム

実用的なルール: Jestを使用したい場合は、チームがアサーションライブラリとモッキングライブラリをランナーと組み合わせる必要があるかどうかを尋ねる必要がある場合、確かにJestを使用したいと思います。

私が大多数のチームに推奨するもの

大多数の現代的なプロジェクトでは、 Jest Jestを使用することを推奨する理由は、Mochaを使用することの強い理由と逆です。Mochaを使用する理由は、 Capacitor Capacitorのライブアップデートの代替品としては、 ElectronElectron

Mochaは、既存のエコシステムがすでに確立されている古いNode.jsサービスまたは長期間のコードベースでまだ意味があります。ただし、mid-levelエンジニアがスクラッチから強力なセットアップを実行する場合、Jestは通常、より多くの摩擦を生み出すことよりも、より多くの摩擦を削減します。

CypressとPlaywrightは素晴らしいツールですが、異なる問題を解決します。ブラウザレベルとエンドツーエンドのチェックに適していますが、ユニットテストのJavaScriptの内部ループでは、Jestが機能する場所ではありません。

A clean testing setup should be dull. If adding the first test feels complicated, the suite probably won’t stay healthy.

眼鏡を着た男性が木製の机に置かれたノートパソコンでプログラミングプロジェクトに取り組んでいます。

A simple Jest setup

最初は、すでにJavaScriptプロジェクトを持っている場合に始めましょう。次に、Jestを開発依存モジュールとして追加し、テストスクリプトを設定します。 package.jsonThat’s enough for many projects. You can add more configuration later if your module system, transpilation, or monorepo structure requires it.

{
  "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__

Write the test before the code

テストを書く前に__CAPGO_KEEP_0__を書くことは、単に個人的な好みではありません。アメリカの消費者金融保護局のJavaScriptガイドでは、テストを書く前に__CAPGO_KEEP_0__を書くことを明確に推奨しています。 writing the test first、テストを整理する describeit, とテストの枠組みを設定する expect(...)JavaScriptのユニットテストガイドライン.

それが重要なのは、テスト駆動開発が設計方法を変えるからです。codeの関数は小さくなり、依存関係が明確になり、副作用が論理に混入するのを防ぐからです。

ここに最小限の例があります。

// 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 パターンは、テストが複雑になるにつれても読みやすく保つ

  1. Arrange 入力と必要なセットアップ。
  2. アクション 関数を呼び出す
  3. 確認 結果

検証ヘルパーに適用される

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);
  });
});

小さなテストは長く生きる。テストは通常、1 つの質問に答えるべきであり、全体のワークフローを語るべきではない。

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.

モックと非同期Codeのマスター

アプリケーションcodeの多くのバグは、2 つの数字を加算することから来ません。外部に達するcodeが原因です: ネットワークリクエスト、ファイル、プラグインAPI、タイマー、IPCチャネル、ストレージレイヤー。

モッキングはそこで役立ちます。境界を制御するので、テストはcodeの決定を焦点にできます。

マイクロサービスアーキテクチャの白板図。API、データストア、外部サービス、イベントドライブデータフローを示しています。

モック境界を設定せず

保守可能なテストガイドは 単一の行動範囲のカバレッジを強調しています そして 1 つの強力なアサーションごとにテスト, そしてまた、モックを過度に使用すると、テストが実装の詳細に依存し、脆弱になり、実際の動作をテストするのではなく、関数が他の関数を呼び出す順序が「正しい」かどうかをテストするのではなく、モックを使用することの警告をまとめた TestRailの記事.

保守可能なユニットテスト

モックを多用するテストの悪い目標:

  • ヘルパーAがヘルパーBを呼び出したか
  • サービスCがシリアライザーDを呼び出したか
  • 内部プライベート関数が2回実行されたか

より良い対象:

  • 関数が返した値
  • 依存関係が失敗した場合に正しく処理したかどうか
  • データを期待どおりの形に変換したかどうか

より良いパターン: 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でもそのパターンが機能します。ネイティブAPI、ファイルアクセス、またはシェル統合を薄いアダプターで囲みます。ユニットテストはサービス層に当たり、実行環境に直接当たるのではなくします。 ipcRendererチームがリリースロジックやアップデートパスを __CAPGO_KEEP_0__ アプリケーションでテストしている場合、 __CAPGO_KEEP_1__ には OTA更新をモックシナリオでテストするためのガイドがあります。

For teams testing release logic and update paths in Capacitor apps, Capgo has a relevant guide on Capacitor.

Electron

非同期フローを不安定性なくテストする

使用 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__がPromiseを返す場合に使用します。コールバックが多く含まれるパターンよりも明確で、デバッグも容易です。

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');
});

また、失敗パスのテストも行ってください:

両方のパス(ハッピーパスとアグリーペス)をテストしてください。実際のアプリケーションでは、ユーザーは失敗パスを思い出すことが多いです。

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秒以内に完了するべきであると述べています。 10秒以内、そしてpre-commitチェックは5秒以内に完了するべきです。 5秒以内この OpenReplayテストガイド.

私はそれを予算ツールとして扱いますが、宗教ではありません。主な努力がエンドツーエンドテストに費やされると、チームはフィードバックを長く待つことになります。すべてがユニットのみの場合、システムの境界を実際に無視することになります。

For a Capacitor or Electron app, a healthy balance usually looks like this:

  • ユニットテスト 価格ロジック、パーミッションルール、シリアライゼーション、更新の有効性、機能フラグ、状態変換のための
  • 統合テスト ストレージアダプター、プラグインラッパー、IPC契約のための
  • E2Eテスト ログイン、購入フロー、同期、または更新の促進などの重要なジャーニーに対するテスト

カバレッジはランプではなく目標

カバレッジレポートは、重要なロジックの未テストのbranchを発見するのに役立ちますが、チームがカバレッジパーセントを追求することで害を及ぼす場合もあります。

UIのバリデーションが重視されているチームでは、慎重にエッジケースをテストしたログインバリデーターが、重要なロジックの未テストのbranchを発見するのに役立つカバレッジレポートよりも価値があります。特に、フォーム、パーサー、日付ロジック、許可チェックなどの入力が多いcodeの場合です。 バリデーションをマスターするためのフロントエンドフォームバリデーションに関するこのガイドは、ユニットレベルのテスト戦略と組み合わせると、バリデーションが重視されているUIの品質を高めるのに役立ちます。 振る舞いを中心としたテストはリファクタリングに耐える

リレーブルなスイートは、内部のリファクタリングを行うと半分のテストを書き直さなければならないことを許容しないようにすることができます。実装詳細をアサートするのではなく、観察可能な振る舞いをアサートすることによって、そこに到達するのが一番簡単です。

持続可能なユースケース: 振る舞いを中心としたテストはリファクタリングに耐える ユースケースが持続可能な場合:

カバレッジはランプではなく目標

  • 境界条件 例えば、空の入力、null値、無効な型、オーバーサイズの文字列
  • ドメイン結果 例えば、「許可が欠如しているため返却が拒否される」
  • 状態遷移 例えば、「ダウンロードメタデータが検証された後、更新を保留状態にする」

よく使われるケースが壊れる:

  • 内部ヘルパー関数の内部を調べる
  • プライベートメソッドのシーケンスを確認する
  • 呼び出しチェーンのすべての層をモックする

Capgoの記事 __CAPGO_KEEP_0__の記事:アプリの品質保証 は、テスト作業をより広いリリースパイプラインに接続することで、有用である。

CI、Capacitor、およびElectronアプリ用のテスト

1人の開発者のマシン上で実行されるテストだけでは、安全性の網にはならない。ローカルな習慣にしかならない。

CIは、JavaScriptの単体テストをチームインフラに変える。プッシュ、プルリクエスト、またはリリースブランチごとに、同じコマンドと同じ期待値でテストを実行できるようになる。環境の変化が微妙なエラーを引き起こすElectronおよびCapacitorプロジェクトでは、この一貫性がさらに重要になる。

CIをデフォルトの実行パスに設定する

CIには、依存関係のインストールと単体テストの実行を、ローカル開発と同じコマンドで行うようにすることが必要である。

GitHubアクションズワークフローの基本的な設定は、以下のようになる。

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には、Capgoアプリ用のCI/CDの設定方法の実践ガイドがある。 Capacitorプラグインの相互作用をテストする.

単体テストでCapacitorをテストする間違った方法は、プラットフォームのブリッジに依存するnativeプラグインを直接サービスに取り込むことである。テストスイートをプラットフォームブリッジに結び付けることになる。

codeはCapacitorのプラグインである。

より良いパターンは、薄い抽象化です:

// 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 });
});

カメラアクセス、バイオメトリックプロンプト、プッシュトークン登録、ネットワークステータスについても同じ考え方が当てはまります。アダプター内でプラグインの呼び出しを維持し、コントロールできるインターフェイスでアプリロジックをテストしてください。

Testing Electron main renderer and IPC code

Electronアプリには2つの重要なシームがあります: main process code そして renderer process code. テストではこれらをぼかさないでください。

信頼できるセットアップでは、通常、以下を分離します:

  • ビュー モデル、状態、フォーマット、UI側のビジネスロジックのためのレンダラー単位テスト メインプロセス単位テスト
  • メニュー、ファイル操作、そしてアプリライフサイクル決定のための
  • IPC契約テスト メッセージの形状と期待される応答のための

例のIPCラッパー:

// 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つの小さな論理部分を孤立してチェックする 統合テスト 複数のコンポーネントまたはサービスが正しく機能するかどうかをチェックする エンドツーエンドテスト 実行中のアプリケーションを通じてユーザージャーニーを実行する。

ビジネスルールの迅速な信頼性のためにユニットテストを使用します。ストレージ、プラグインラッパー、IPCなどのシームのために統合テストを使用します。E2Eテストは、破壊されることによる大きな損害を与えるワークフローにのみ使用してください。

完全なカバレージを目指すべきか

いいえ。完全なカバレージはチームを低価値のテストに導く可能性があります。

カバレージは、誰も実行していないリスクのあるcodeを明らかにするときに役立ちます。ダッシュボードを満たすために浅いアサーションを追加するエンジニアがいる時には役立ちません。スイートが脆弱であれば、カバレージを増やすことでそれを救うことはできません。

既存のコードベースにテストを追加するには

変更がすでに発生している場所から始めましょう。チームを凍結し、テスト戦略の大規模なリライトを発表するのを避けましょう。

実用的なシーケンスは次のようになります。

チームが


__CAPGO_KEEP_0__ Capacitor Capacitor Live Updateプラットフォーム Electron Live Updateプラットフォーム アプリとJavaScriptの変更に対するよりきれいなリリースプロセスが必要です Capgo CapacitorJSとElectronアプリに対するリアルタイムの更新が提供され、ロールアウトの制御と可視性が実現され、チームは単純なユニットテストと、ストアのレビュー待たずにウェブバンドの変更を安全に配信できるようになります

Capacitor アプリ向けの即時更新

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

ウェブ層のバグが生じた場合、__CAPGO_KEEP_0__ を通じて修正を配信し、App Storeの承認待ちの日数を待たずしてユーザーに更新を提供する。ネイティブの変更は通常のレビュー経路に従う。

スタートする

最新のブログ

Capgo gives you the best insights you need to create a truly professional mobile app.