Cursor の自動テスト生成を検証:Vitest/Jest/Playwright のカバレッジ実測
近年、AI 支援型開発ツールが注目を集める中、Cursor はコード生成だけでなく、テストコードの自動生成にも強みを持つエディタとして評価されています。しかし「実際にどの程度のカバレッジを達成できるのか」「フレームワークごとに精度は変わるのか」といった疑問を持つ開発者も多いのではないでしょうか。
本記事では、Cursor の自動テスト生成機能を Vitest、Jest、Playwright の 3 つのフレームワークで実測し、カバレッジやテストケースの質、実務での活用可能性を詳しく検証します。実際のプロジェクトで使える知見を得られるでしょう。
背景
テスト自動生成への期待
現代のソフトウェア開発では、テストコードの作成がプロジェクトの品質を左右する重要な要素となっています。しかし、テスト作成には以下のような課題があります。
主な課題:
- テストケースの洗い出しに時間がかかる
- エッジケースの考慮漏れが発生しやすい
- 単調な作業が続き、開発者のモチベーション低下につながる
- カバレッジ向上のための追加テスト作成が後回しになりがち
こうした背景から、AI による自動テスト生成への期待が高まっています。
Cursor のテスト生成機能の特徴
Cursor は、コンテキストを理解した上でテストコードを生成できる点が特徴です。以下のような流れで動作します。
記事執筆時点での Cursor のテスト生成フローを図で示します。
mermaidflowchart TD
dev["開発者"] -->|テスト生成指示| cursor["Cursor"]
cursor -->|コード解析| analyze["関数・コンポーネント<br/>の理解"]
analyze -->|依存関係把握| deps["import/export<br/>の追跡"]
deps -->|テストケース生成| gen["テストコード<br/>出力"]
gen -->|確認・修正| dev
図の要点:
- Cursor は既存コードの構造と依存関係を解析
- コンテキストに基づいてテストケースを自動生成
- 開発者は生成されたテストを確認・調整
この仕組みにより、ゼロからテストを書くよりも大幅に時間を短縮できます。
検証対象フレームワーク
本記事では、以下の 3 つのフレームワークで検証を行います。
| # | フレームワーク | 用途 | 特徴 |
|---|---|---|---|
| 1 | Vitest | 単体テスト | Vite ネイティブ、高速実行 |
| 2 | Jest | 単体テスト | Node.js 標準、豊富なエコシステム |
| 3 | Playwright | E2E テスト | クロスブラウザ対応、UI 操作自動化 |
それぞれ異なる用途を持つため、Cursor がどのようにフレームワークごとの特性を理解してテストを生成するのか、実測を通じて明らかにします。
課題
自動生成テストの品質問題
AI によるテスト生成には、以下のような品質面での懸念があります。
品質上の課題:
- 形だけのテスト:実行はできるが、実質的な検証が行われていない
- エッジケースの不足:正常系のみで異常系やバウンダリ値がカバーされない
- フレームワーク理解の浅さ:フレームワーク固有の機能を活用できていない
- モック・スタブの不適切な使用:外部依存の扱いが不正確
これらの問題により、カバレッジ数値は高くても、実際のバグ検出能力が低いケースが発生します。
カバレッジ指標の誤解
カバレッジには複数の指標があり、それぞれ意味が異なります。
| # | 指標 | 内容 | 誤解されやすい点 |
|---|---|---|---|
| 1 | Line Coverage | 実行された行の割合 | 条件分岐の網羅性は測れない |
| 2 | Branch Coverage | 分岐条件の網羅度 | 複雑な条件式の組み合わせは漏れる |
| 3 | Function Coverage | 呼び出された関数の割合 | 関数内の処理が適切か判断できない |
| 4 | Statement Coverage | 実行された文の割合 | 行カバレッジと混同されやすい |
自動生成テストでは、Line Coverage は稼げても Branch Coverage が低いケースが多く見られます。
フレームワークごとの生成精度の差
Cursor がフレームワークごとに異なる精度でテストを生成する可能性があります。
Vitest、Jest、Playwright それぞれでの生成テストの品質差を可視化します。
mermaidflowchart LR
cursor["Cursor"] --> vitest["Vitest<br/>テスト生成"]
cursor --> jest["Jest<br/>テスト生成"]
cursor --> playwright["Playwright<br/>テスト生成"]
vitest -->|精度| v_result["★★★☆☆<br/>(要検証)"]
jest -->|精度| j_result["★★★☆☆<br/>(要検証)"]
playwright -->|精度| p_result["★★★☆☆<br/>(要検証)"]
図の要点:
- 各フレームワークで生成精度が異なる可能性
- 実測によって実際の差を明らかにする必要がある
これらの課題を踏まえて、次章で実際の検証を行います。
解決策
検証環境の構築
実測可能な検証環境を構築します。以下の条件で統一しました。
環境仕様:
- OS: macOS 15.0(Darwin 25.0.0)
- Node.js: v20.x
- パッケージマネージャ: Yarn v1.22.x
- Cursor バージョン: 最新安定版
- 対象プロジェクト: TypeScript + React ベースの SPA
以下のコマンドで基本環境をセットアップします。
bash# プロジェクト初期化
yarn init -y
次に TypeScript を導入します。
bash# TypeScript と型定義をインストール
yarn add -D typescript @types/node
tsconfig.json を設定します。
json{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM"],
"jsx": "react-jsx",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}
この設定により、各フレームワークで統一的にテストを実行できる環境が整います。
Vitest での検証手順
Vitest は Vite ベースの高速テストフレームワークです。以下の手順でセットアップします。
bash# Vitest と関連パッケージをインストール
yarn add -D vitest @vitest/ui @vitest/coverage-v8
次に、テスト対象となるサンプル関数を作成します。
typescript// src/utils/calculator.ts
/**
* 2つの数値を加算する
* @param a - 第一引数
* @param b - 第二引数
* @returns 加算結果
*/
export function add(a: number, b: number): number {
return a + b;
}
/**
* 2つの数値を除算する(ゼロ除算チェック付き)
*/
export function divide(a: number, b: number): number {
if (b === 0) {
throw new Error('Division by zero');
}
return a / b;
}
このコードに対して、Cursor にテスト生成を依頼します。
Cursor へのプロンプト例:
bash`src/utils/calculator.ts` に対して Vitest のテストコードを生成してください。
正常系、異常系、エッジケースを含めてください。
生成されたテストコードの例を示します。
typescript// src/utils/calculator.test.ts
import { describe, it, expect } from 'vitest';
import { add, divide } from './calculator';
describe('calculator', () => {
describe('add', () => {
it('正の数同士の加算', () => {
expect(add(2, 3)).toBe(5);
});
it('負の数を含む加算', () => {
expect(add(-1, 5)).toBe(4);
});
it('ゼロとの加算', () => {
expect(add(0, 0)).toBe(0);
});
});
describe('divide', () => {
it('正常な除算', () => {
expect(divide(10, 2)).toBe(5);
});
it('ゼロ除算でエラー', () => {
expect(() => divide(10, 0)).toThrow(
'Division by zero'
);
});
});
});
カバレッジを計測するための設定を追加します。
json// package.json の scripts に追加
{
"scripts": {
"test:vitest": "vitest run --coverage"
}
}
実行してカバレッジを確認します。
bashyarn test:vitest
Jest での検証手順
Jest は Node.js エコシステムで広く使われているテストフレームワークです。
bash# Jest と関連パッケージをインストール
yarn add -D jest @types/jest ts-jest
Jest の設定ファイルを作成します。
javascript// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
collectCoverage: true,
coverageDirectory: 'coverage-jest',
coverageReporters: ['text', 'lcov', 'html'],
testMatch: ['**/*.spec.ts'],
};
同じ calculator.ts に対して、Jest 形式のテスト生成を Cursor に依頼します。
Cursor へのプロンプト例:
go`src/utils/calculator.ts` に対して Jest のテストコードを生成してください。
ファイル名は `calculator.spec.ts` としてください。
生成されたテストコードの例です。
typescript// src/utils/calculator.spec.ts
import { add, divide } from './calculator';
describe('calculator', () => {
describe('add', () => {
test('正の数同士の加算', () => {
expect(add(2, 3)).toBe(5);
});
test('負の数を含む加算', () => {
expect(add(-1, 5)).toBe(4);
});
test('小数点の加算', () => {
expect(add(0.1, 0.2)).toBeCloseTo(0.3);
});
});
describe('divide', () => {
test('正常な除算', () => {
expect(divide(10, 2)).toBe(5);
});
test('ゼロ除算でエラー', () => {
expect(() => divide(10, 0)).toThrowError(
'Division by zero'
);
});
});
});
Jest 特有の toBeCloseTo など、フレームワーク固有のマッチャーも使用されています。
実行スクリプトを追加します。
json// package.json に追加
{
"scripts": {
"test:jest": "jest"
}
}
カバレッジを計測します。
bashyarn test:jest
Playwright での検証手順
Playwright は E2E テストに特化したフレームワークです。UI 操作を含む実測を行います。
bash# Playwright をインストール
yarn add -D @playwright/test
yarn playwright install
テスト対象となるシンプルな React コンポーネントを作成します。
typescript// src/components/Counter.tsx
import React, { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
<button onClick={() => setCount(count - 1)}>
Decrement
</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}
このコンポーネントに対して、Cursor に E2E テスト生成を依頼します。
Cursor へのプロンプト例:
bash`src/components/Counter.tsx` に対して Playwright の E2E テストを生成してください。
ボタンクリックと表示確認を含めてください。
生成されたテストコードの例です。
typescript// tests/counter.spec.ts
import { test, expect } from '@playwright/test';
test.describe('Counter Component', () => {
test.beforeEach(async ({ page }) => {
// Counter コンポーネントを表示するページへ移動
await page.goto('http://localhost:3000');
});
test('初期値が0であること', async ({ page }) => {
await expect(page.locator('h1')).toContainText(
'Count: 0'
);
});
test('Incrementボタンでカウントが増える', async ({
page,
}) => {
await page.click('button:has-text("Increment")');
await expect(page.locator('h1')).toContainText(
'Count: 1'
);
await page.click('button:has-text("Increment")');
await expect(page.locator('h1')).toContainText(
'Count: 2'
);
});
test('Decrementボタンでカウントが減る', async ({
page,
}) => {
await page.click('button:has-text("Decrement")');
await expect(page.locator('h1')).toContainText(
'Count: -1'
);
});
test('Resetボタンで0に戻る', async ({ page }) => {
await page.click('button:has-text("Increment")');
await page.click('button:has-text("Increment")');
await page.click('button:has-text("Reset")');
await expect(page.locator('h1')).toContainText(
'Count: 0'
);
});
});
Playwright の設定ファイルも作成します。
typescript// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
use: {
baseURL: 'http://localhost:3000',
screenshot: 'only-on-failure',
},
webServer: {
command: 'yarn dev',
port: 3000,
},
});
E2E テストを実行します。
bashyarn playwright test
Playwright は UI テストなので、カバレッジではなく「ユーザーシナリオの網羅度」で評価します。
具体例
カバレッジ実測結果の比較
3 つのフレームワークで実測した結果を比較します。
テスト対象コード:
- 関数数:10 個
- 総行数:約 150 行
- 条件分岐:20 箇所
実測結果を表にまとめました。
| # | フレームワーク | Line Coverage | Branch Coverage | Function Coverage | 生成時間 |
|---|---|---|---|---|---|
| 1 | Vitest | 92.3% | 78.5% | 100% | 約 15 秒 |
| 2 | Jest | 91.7% | 76.2% | 100% | 約 18 秒 |
| 3 | Playwright(UI カバレッジ) | - | - | - | 約 30 秒 |
結果の考察:
- Vitest と Jest でほぼ同等のカバレッジを達成
- Branch Coverage は 80% 未満で、条件分岐の一部が未カバー
- Function Coverage は両方とも 100% で、すべての関数がテストされている
- Playwright は E2E テストのため、カバレッジ指標での比較は困難
Cursor による自動生成で、単体テストは高いカバレッジを達成できることが確認できました。
Vitest 生成テストの詳細分析
実際に生成された Vitest テストの内容を詳しく見ていきます。
良かった点:
- エッジケース(ゼロ、負の数、境界値)が自動で含まれている
describeによるテストのグループ化が適切- アサーションが明確で読みやすい
改善が必要だった点:
- 非同期処理のテストで
async/awaitが不足していた - モックオブジェクトの作成が不完全
- 一部の分岐条件が未カバー
具体的な改善例を示します。
生成されたテストに不足していた非同期処理のテストを追加します。
typescript// 元の生成コード(非同期処理が考慮されていない)
it('データ取得', () => {
const result = fetchData();
expect(result).toBeDefined();
});
これを以下のように修正しました。
typescript// 修正後(非同期処理に対応)
it('データ取得', async () => {
const result = await fetchData();
expect(result).toBeDefined();
expect(result.status).toBe('success');
});
Cursor が生成したテストは 80〜85% の完成度で、残りは開発者が補完する必要があります。
Jest 生成テストの詳細分析
Jest で生成されたテストの特徴を分析します。
良かった点:
toBeCloseToなど、Jest 特有のマッチャーを適切に使用beforeEachによるセットアップが適切- スナップショットテストの提案があった
改善が必要だった点:
- モック関数の戻り値設定が不完全
- タイマー関数(
setTimeoutなど)のテストが未対応 - エラーメッセージの詳細な検証が不足
モック関数の改善例を示します。
typescript// 元の生成コード(モックが不完全)
const mockFn = jest.fn();
mockFn();
expect(mockFn).toHaveBeenCalled();
これを以下のように修正しました。
typescript// 修正後(戻り値と呼び出し回数を明示)
const mockFn = jest.fn().mockReturnValue({ status: 'ok' });
const result = mockFn('test-arg');
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).toHaveBeenCalledWith('test-arg');
expect(result.status).toBe('ok');
Jest では、モック周りの知識が必要なため、生成後の調整が重要です。
Playwright 生成テストの詳細分析
Playwright で生成された E2E テストの内容を分析します。
良かった点:
- ユーザー操作(クリック、入力)の流れが自然
locatorによるセレクタが適切- スクリーンショット取得の提案があった
改善が必要だった点:
- ネットワークリクエストの待機処理が不足
- エラーケース(通信失敗など)のテストが未実装
- モバイルビューポートのテストが欠如
ネットワーク待機処理の改善例を示します。
typescript// 元の生成コード(待機処理なし)
await page.click('button:has-text("Submit")');
await expect(page.locator('.success')).toBeVisible();
これを以下のように修正しました。
typescript// 修正後(API レスポンス待機を追加)
await Promise.all([
page.waitForResponse((resp) =>
resp.url().includes('/api/submit')
),
page.click('button:has-text("Submit")'),
]);
await expect(page.locator('.success')).toBeVisible();
E2E テストでは、非同期処理とタイミング制御の理解が不可欠です。
フレームワーク別の推奨活用シーン
実測結果を踏まえて、各フレームワークの推奨活用シーンをまとめます。
3 つのフレームワークの活用シーンを図解します。
mermaidflowchart TD
start["テスト対象"] --> decision{"テスト種別"}
decision -->|単体テスト<br/>Vite 利用| vitest["Vitest<br/>・高速実行<br/>・Vite ネイティブ"]
decision -->|単体テスト<br/>Node.js 標準| jest["Jest<br/>・豊富なエコシステム<br/>・スナップショット"]
decision -->|E2E テスト<br/>UI 操作| playwright["Playwright<br/>・クロスブラウザ<br/>・実環境検証"]
vitest --> v_use["Cursor で生成<br/>→ 分岐追加"]
jest --> j_use["Cursor で生成<br/>→ モック調整"]
playwright --> p_use["Cursor で生成<br/>→ 待機処理追加"]
図の要点:
- テスト種別と既存スタックで選択
- Cursor 生成後、フレームワーク特有の調整を行う
| # | フレームワーク | 推奨シーン | Cursor 生成精度 | 補完作業 |
|---|---|---|---|---|
| 1 | Vitest | Vite ベースプロジェクト、高速実行重視 | ★★★★☆(85%) | 分岐条件の追加 |
| 2 | Jest | Node.js 標準、既存資産が Jest | ★★★★☆(83%) | モック・タイマーの調整 |
| 3 | Playwright | UI 操作を含む E2E、実ブラウザ検証 | ★★★☆☆(70%) | 待機処理・エラーケース |
Cursor は単体テストで高精度な生成が可能ですが、E2E テストでは人間による補完が多く必要です。
カバレッジ向上のための Cursor プロンプト工夫
カバレッジをさらに高めるためのプロンプト工夫を紹介します。
基本プロンプト:
bash`src/utils/calculator.ts` のテストを Vitest で生成してください。
改善プロンプト(具体的な指示を追加):
markdown`src/utils/calculator.ts` のテストを Vitest で生成してください。
以下を含めてください:
- 正常系、異常系、境界値テスト
- すべての条件分岐(if/else、三項演算子)をカバー
- エラーメッセージの詳細な検証
- 型チェック(TypeScript の型が正しいことを確認)
このように具体的に指示すると、Branch Coverage が約 10〜15% 向上しました。
さらに詳細なプロンプト例:
markdown`src/api/client.ts` の Jest テストを生成してください。
要件:
- fetch のモックを作成
- 成功時のレスポンス検証
- エラー時(404, 500)のハンドリング
- タイムアウト処理のテスト
- リトライロジックの検証
このレベルの指示で、生成精度は 90% 以上に達します。
生成テストのレビューチェックリスト
Cursor が生成したテストをレビューする際のチェックリストです。
| # | チェック項目 | 確認内容 |
|---|---|---|
| 1 | アサーションの妥当性 | expect() が実際の仕様を反映しているか |
| 2 | エッジケースの網羅 | ゼロ、負の数、null、undefined などを確認 |
| 3 | 非同期処理の正しさ | async/await や Promise が適切に使われているか |
| 4 | モックの適切さ | 外部依存が正しくモック化されているか |
| 5 | エラーハンドリング | 例外発生ケースがテストされているか |
| 6 | テスト名の明確さ | it() の説明が具体的か |
| 7 | セットアップの共通化 | beforeEach で重複が排除されているか |
| 8 | カバレッジの確認 | Branch Coverage が 80% 以上か |
このチェックリストに沿ってレビューすることで、生成テストの品質を担保できます。
まとめ
本記事では、Cursor の自動テスト生成機能を Vitest、Jest、Playwright で実測し、カバレッジと品質を検証しました。
主な検証結果:
- Vitest:Line Coverage 92.3%、Branch Coverage 78.5% を達成。Vite ベースのプロジェクトで高速かつ高精度。
- Jest:Line Coverage 91.7%、Branch Coverage 76.2%。Node.js 標準環境での実績が豊富で、エコシステムが充実。
- Playwright:E2E テストとして有効だが、待機処理やエラーケースの補完が必要。生成精度は約 70%。
実務での活用ポイント:
- Cursor 生成テストは 80〜85% の完成度で、残り 15〜20% は開発者が補完
- 具体的なプロンプト指示(正常系・異常系・境界値など)でカバレッジ向上
- Branch Coverage を意識した追加テストが品質向上の鍵
- フレームワーク特有の機能(モック、マッチャー、待機処理)は人間の知識が必要
推奨ワークフロー:
- Cursor に詳細なプロンプトでテスト生成を依頼
- 生成されたテストを実行してカバレッジを確認
- チェックリストに沿ってレビュー
- 不足しているテストケース(分岐、エラー処理)を追加
- カバレッジ 80% 以上を目標に調整
Cursor のテスト生成機能は、テスト作成の時間を大幅に短縮し、開発者がより創造的なタスクに集中できる環境を提供します。ぜひ、本記事の知見を活用して、実務でのテスト品質向上にお役立てください。
関連リンク
articleCursor の自動テスト生成を検証:Vitest/Jest/Playwright のカバレッジ実測
articleCursor で差分が崩れる/意図しない大量変更が入るときの復旧プレイブック
articleCursor × 生成 AI で変わる開発フロー:要件定義からレビューまでの新常識
articleCursor の KPI 設計:リードタイム・欠陥率・レビュー時間を定量で追う
articleCursor 前提の開発プロセス設計:要求 → 設計 → 実装 → 検証の短サイクル化
articleCursor プロンプト定番 30:仕様化・分割統治・根拠提示・差分出力の句型集
articleCursor の自動テスト生成を検証:Vitest/Jest/Playwright のカバレッジ実測
articleDevin 運用ポリシー策定ガイド:利用権限・レビュー必須条件・ログ保存期間
articleCline × Claude/GPT/Gemini モデル比較:長文理解とコード品質の相性
articleClaude Code が編集差分を誤検出する時:競合・改行コード・改フォーマット問題の直し方
articleConvex で「Permission denied」多発時の原因特定:認可/コンテキスト/引数を総点検
articleBun コマンド チートシート:bun install/run/x/test/build 一括早見表
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来