jasmine、jest、mocha、qunit はいずれもJavaScript向けのユニットテストおよび統合テストを実行するためのテストフレームワークです。これらは共通してテストケースの定義、実行、結果のアサーションをサポートしますが、構成の柔軟性、組み込み機能、エコシステムとの統合方法に大きな違いがあります。特に、モックやスナップショットテスト、テストランナーの使いやすさ、非同期処理の扱い方など、実際の開発フローに深く関わる部分で選択基準が分かれます。
フロントエンド開発において、テストフレームワークの選択は開発速度や保守性に大きな影響を与えます。jasmine、jest、mocha、qunit はそれぞれ異なる哲学で設計されており、プロジェクトの要件に応じて最適な選択が必要です。この記事では、実際のコード例を交えながら、各フレームワークの強みと弱みを深く掘り下げます。
jasmine、jest、mocha は共通して describe / it スタイルを採用しています。これはBDD(振る舞い駆動開発)由来の記法で、テストの階層構造を自然に表現できます。
// jasmine / jest / mocha 共通スタイル
describe('Calculator', () => {
it('adds two numbers correctly', () => {
expect(add(1, 2)).toBe(3);
});
});
一方、qunit は独自のAPIを持ち、QUnit.test() を使います。また、グローバル関数として利用できるため、HTMLファイルに直接埋め込むことも容易です。
// qunit
QUnit.test('Calculator adds two numbers correctly', (assert) => {
assert.equal(add(1, 2), 3);
});
💡 注意:
mocha自体はアサーションライブラリを含まないため、上記のexpect().toBe()はchaiやnode:assertなど別途導入する必要があります。
jasmine は独自のマッチャーセットを内蔵しており、toBe()、toEqual()、toContain() などがすぐに使えます。
// jasmine
expect([1, 2, 3]).toContain(2);
expect(promise).toBeResolved(); // 非同期専用マッチャー
jest も同様に豊富なビルトインマッチャーを持ち、さらに拡張も容易です。
// jest
expect(user).toMatchObject({ name: 'Alice' });
expect(fetchData).rejects.toThrow();
mocha はアサーションエンジンを含まないため、以下のように外部ライブラリと組み合わせる必要があります。
// mocha + chai
const { expect } = require('chai');
expect(result).to.deep.equal(expected);
qunit はシンプルなアサーションメソッド(equal、deepEqual、ok など)を提供しますが、マッチャーの表現力は限定的です。
// qunit
assert.deepEqual(obj1, obj2);
assert.ok(condition);
jasmine は spyOn() で関数の監視やスタブが可能です。
// jasmine
spyOn(console, 'log');
myFunction();
expect(console.log).toHaveBeenCalledWith('hello');
jest はモック機能が非常に強力で、関数全体を自動的にモックすることもできます。
// jest
jest.spyOn(console, 'log');
// または
const mockFn = jest.fn();
mockFn.mockReturnValue('test');
mocha はモック機能を含まないため、通常は sinon を併用します。
// mocha + sinon
const spy = sinon.spy(console, 'log');
myFunction();
expect(spy.calledWith('hello')).to.be.true;
qunit は @sinonjs/fake-timers や sinon と組み合わせることが一般的ですが、公式サポートはありません。
// qunit + sinon
const stub = sinon.stub(window, 'fetch');
stub.resolves({ json: () => ({}) });
jest はスナップショットテストをネイティブサポートしており、Reactコンポーネントやデータ構造の変更を簡単に追跡できます。
// jest
it('renders correctly', () => {
const tree = renderer.create(<Button />).toJSON();
expect(tree).toMatchSnapshot();
});
jasmine、mocha、qunit はスナップショットテストを直接サポートしていません。必要であれば、jest-snapshot を個別に導入するか、カスタムマッチャーを実装する必要があります。
qunit はHTMLベースのテストランナーを提供し、ブラウザで直接テストを実行できます。デバッグが非常に簡単です。
<!-- qunit HTML runner -->
<div id="qunit"></div>
<script src="qunit.js"></script>
<script src="tests.js"></script>
jasmine もブラウザ向けのスタンドアロン版を提供しており、同様にHTMLで実行可能です。
mocha は mocha.js とCSSをHTMLに読み込むことでブラウザ実行が可能ですが、設定が必要です。
jest はデフォルトでJSDOM上で動作し、実際のブラウザとは異なる環境でテストが実行されます。実ブラウザでのテストには jest-playwright や jest-puppeteer のような追加パッケージが必要です。
jest は「ゼロコンフィグ」を謳っており、多くのプロジェクトで追加設定なしに動作します。BabelやTypeScriptとの統合も自動で行われます。
jasmine も最小限の設定で動作しますが、高度なカスタマイズ(例:カスタムレポーター)には設定ファイルが必要です。
mocha は極めて柔軟で、レポーター、タイムアウト、フックの挙動などを細かく制御できますが、その分初期設定が複雑になりがちです。
qunit は設定オプションが少なく、シンプルさを重視した設計になっています。
すべてのフレームワークが非同期テストをサポートしていますが、書き方に違いがあります。
jasmine:
it('fetches data', async () => {
const data = await fetchData();
expect(data).toBeTruthy();
});
jest:
it('fetches data', async () => {
const data = await fetchData();
expect(data).toBeTruthy();
});
mocha:
it('fetches data', async () => {
const data = await fetchData();
// アサーションはchaiなどで行う
});
qunit:
QUnit.test('fetches data', async (assert) => {
const data = await fetchData();
assert.ok(data);
});
| 特徴 | jasmine | jest | mocha | qunit |
|---|---|---|---|---|
| 設定の手間 | 小 | 最小(ゼロコンフィグ) | 大(柔軟だが複雑) | 小 |
| ビルトイン機能 | アサーション・スパイ完備 | アサーション・モック・スナップショット完備 | なし(外部依存) | 基本的なアサーションのみ |
| ブラウザ対応 | ○(スタンドアロン版あり) | △(JSDOM前提) | ○(設定必要) | ◎(HTMLランナー標準) |
| モダン機能 | 限定的 | 豊富(スナップショットなど) | 外部パッケージ次第 | ほぼなし |
| 学習コスト | 低 | 低〜中 | 中〜高 | 低 |
jest が最もスムーズjasmine または qunitmocha + Chai/Sinonqunit が伝統的に使われる最終的には、チームのスキルセット、プロジェクトの規模、必要な機能セットを総合的に判断して選ぶことが重要です。
jest を選ぶべきなのは、ReactやVueなどのモダンフロントエンドフレームワークを使ったプロジェクトで、スナップショットテストや自動モック、カバレッジレポートをすぐに使いたい場合です。ゼロコンフィグで動作し、並列実行やウォッチモードなど開発者体験に特化した機能が豊富です。ただし、内部でJSDOMをデフォルトで使用するため、実際のブラウザ環境での挙動を正確に再現したい場合は注意が必要です。
jasmine を選ぶべきなのは、設定不要で即座にテストを書き始めたい場合、またはブラウザとNode.jsの両方で同じテストコードを使いたいシナリオです。すべての機能(テストダブル、マッチャー、非同期サポート)が単一パッケージに内蔵されており、外部依存が少ないため、シンプルなプロジェクトや教育目的に向いています。ただし、モダンな開発体験(例:スナップショットテスト、自動モック)が必要な場合は物足りなくなる可能性があります。
mocha を選ぶべきなのは、テストランナーとしての柔軟性を重視し、アサーションライブラリ(Chaiなど)やモックツール(Sinonなど)を自由に組み合わせたい場合です。Node.jsとブラウザの両方を広くサポートし、非同期テストやテストフックの制御が細かく可能です。ただし、その柔軟性ゆえに初期セットアップが複雑になりやすく、初心者には敷居が高いかもしれません。
qunit を選ぶべきなのは、jQueryやEmber.jsのような特定のエコシステム(特にjQuery関連プロジェクト)でテストを書く場合、または軽量でブラウザファーストのテスト環境が必要なときです。HTMLベースのテストランナーを持ち、デバッグが直感的に行えます。しかし、モダンな機能(例:スナップショットテスト、ビルトインモック)がなく、大規模アプリケーションのテストには向かない傾向があります。
🃏 Delightful JavaScript Testing
👩🏻💻 Developer Ready: Complete and ready to set-up JavaScript testing solution. Works out of the box for any React project.
🏃🏽 Instant Feedback: Failed tests run first. Fast interactive mode can switch between running all tests or only test files related to changed files.
📸 Snapshot Testing: Jest can capture snapshots of React trees or other serializable values to simplify UI testing.
Read More: https://jestjs.io/