ANTIGRAVITY LABEN
記事一覧/Editor View
Editor View/2026-03-14上級

Antigravity AI でテストコードを自動生成 — 単体・統合・E2E テスト完全戦略

Antigravity338testing15Jest2Playwright2AI10TDD2

取り組みの背景

テストコードの作成は、ソフトウェア開発において最も時間を消費する作業の一つです。単体テスト、統合テスト、E2E テストそれぞれの設計と実装には、ビジネスロジックの深い理解と膨大な準備が必要です。Antigravity AI を活用することで、このテスト作成プロセスを劇的に高速化し、カバレッジを向上させることができます。

単体テスト生成戦略

単体テストは、関数やクラスメソッドの個別動作を検証する最も基本的なテストレベルです。Antigravity AI でこれを自動生成する際のポイントは、ソースコードの構造を正確に解析し、エッジケースを網羅することです。

Antigravity AI でのプロンプト戦略

You are an expert Jest test engineer. Analyze the following TypeScript function and generate comprehensive unit tests.
 
Function signature:
export function calculateShippingCost(weight: number, distance: number, isExpress: boolean): number
 
Requirements:
1. Generate 8-10 test cases covering normal, boundary, and edge cases
2. Include parametrized tests for different weight/distance combinations
3. Test error conditions (negative values, null inputs)
4. Use Jest matchers for clear assertions
5. Follow AAA pattern (Arrange, Act, Assert)
 
Output only valid Jest test code with describe/it blocks.

このプロンプトを Antigravity エージェントに入力すると、以下のような高品質なテストコードが生成されます:

// jest.config.js を想定した単体テスト例
describe('calculateShippingCost', () => {
  describe('normal cases', () => {
    it('should calculate standard shipping cost for domestic orders', () => {
      // Arrange
      const weight = 5;
      const distance = 100;
      const isExpress = false;
 
      // Act
      const result = calculateShippingCost(weight, distance, isExpress);
 
      // Assert
      expect(result).toBeGreaterThan(0);
      expect(result).toBeLessThan(1000);
    });
 
    it('should apply express surcharge when isExpress is true', () => {
      const standardCost = calculateShippingCost(5, 100, false);
      const expressCost = calculateShippingCost(5, 100, true);
 
      expect(expressCost).toBeGreaterThan(standardCost);
    });
  });
 
  describe('boundary conditions', () => {
    it('should handle zero weight correctly', () => {
      expect(() => calculateShippingCost(0, 100, false)).not.toThrow();
    });
 
    it('should reject negative weight', () => {
      expect(() => calculateShippingCost(-5, 100, false)).toThrow();
    });
 
    it('should handle maximum distance value', () => {
      expect(calculateShippingCost(10, 5000, false)).toBeGreaterThan(0);
    });
  });
 
  describe('edge cases', () => {
    const testCases = [
      { weight: 0.1, distance: 1, isExpress: false },
      { weight: 1000, distance: 5000, isExpress: true },
      { weight: 50, distance: 0, isExpress: false }
    ];
 
    test.each(testCases)(
      'should handle edge case: weight=$weight, distance=$distance, isExpress=$isExpress',
      ({ weight, distance, isExpress }) => {
        expect(() => calculateShippingCost(weight, distance, isExpress)).not.toThrow();
      }
    );
  });
});

カバレッジ目標の設定

単体テストにおけるカバレッジ目標は、以下のように段階的に設定します:

  • ステートメントカバレッジ:80% 以上 — すべてのコード行が実行される
  • ブランチカバレッジ:75% 以上 — if/else の両分岐がテストされる
  • ファンクションカバレッジ:90% 以上 — すべての関数が呼び出される

Antigravity AI は、カバレッジギャップを自動的に特定し、追加のテストケースを提案できます。

統合テスト・パターン

統合テストは、複数のモジュール・サービス間の相互作用を検証します。API エンドポイント、データベース接続、外部サービスの連携をテストする際には、モック戦略が重要です。

supertest を用いた API 統合テスト

// API 統合テストの例
const request = require('supertest');
const app = require('../src/app');
 
describe('POST /api/orders', () => {
  it('should create a new order with valid payload', async () => {
    const payload = {
      customerId: 'cust-123',
      items: [
        { productId: 'prod-001', quantity: 2 },
        { productId: 'prod-002', quantity: 1 }
      ],
      shippingAddress: '123 Main St'
    };
 
    const response = await request(app)
      .post('/api/orders')
      .send(payload)
      .expect(201);
 
    expect(response.body).toHaveProperty('orderId');
    expect(response.body.status).toBe('pending');
    expect(response.body.total).toBeGreaterThan(0);
  });
 
  it('should validate required fields', async () => {
    const invalidPayload = {
      items: [] // customerId と shippingAddress が未定義
    };
 
    await request(app)
      .post('/api/orders')
      .send(invalidPayload)
      .expect(400);
  });
 
  it('should handle database errors gracefully', async () => {
    // データベースモックをエラー状態に設定
    jest.spyOn(global, 'db').mockRejectedValueOnce(new Error('DB unavailable'));
 
    const payload = {
      customerId: 'cust-123',
      items: [{ productId: 'prod-001', quantity: 1 }],
      shippingAddress: '123 Main St'
    };
 
    const response = await request(app)
      .post('/api/orders')
      .send(payload)
      .expect(500);
 
    expect(response.body.error).toBeDefined();
  });
});

Antigravity エージェントワークフロー

統合テスト生成時には、以下のエージェントワークフローを推奨します:

  1. 依存関係マッピング — サービス間の依存関係を自動抽出
  2. モック戦略の決定 — どのサービスをモック化するかを判定
  3. テストシナリオ生成 — 正常系・異常系・エッジケースの自動生成
  4. アサーション設計 — 期待される出力と副作用の検証

E2E テスト戦略(Playwright)

E2E テストは、ユーザーの実際のワークフローをブラウザレベルで検証します。Playwright を使用することで、複数ブラウザ間でのクロスプラットフォームテストが可能になります。

Playwright テストの自動生成

// Playwright E2E テストの例
import { test, expect } from '@playwright/test';
 
test.describe('E-commerce Checkout Flow', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('https://example.com/products');
  });
 
  test('should complete purchase from product search to order confirmation', async ({ page }) => {
    // 商品検索
    await page.fill('input[placeholder="Search products"]', 'laptop');
    await page.click('button:has-text("Search")');
    await page.waitForSelector('[data-testid="product-card"]');
 
    // 最初の商品をクリック
    await page.click('[data-testid="product-card"]:first-child');
    await expect(page).toHaveURL(/\/product\/\d+$/);
 
    // 商品詳細を確認
    const price = await page.textContent('[data-testid="price"]');
    expect(price).toMatch(/\$\d+\.\d{2}/);
 
    // カートに追加
    await page.click('button:has-text("Add to Cart")');
    const cartBadge = await page.textContent('[data-testid="cart-count"]');
    expect(cartBadge).toBe('1');
 
    // チェックアウト画面へ
    await page.click('[data-testid="cart-icon"]');
    await page.click('button:has-text("Proceed to Checkout")');
 
    // 配送情報を入力
    await page.fill('input[name="address"]', '123 Main Street');
    await page.fill('input[name="city"]', 'Springfield');
    await page.selectOption('select[name="country"]', 'US');
 
    // 支払い情報を入力
    const frameHandle = await page.$('iframe[title="Payment form"]');
    const paymentFrame = await frameHandle.contentFrame();
    await paymentFrame.fill('input[name="cardnumber"]', '4111111111111111');
 
    // 注文を確定
    await page.click('button:has-text("Place Order")');
 
    // 確認ページを検証
    await expect(page).toHaveURL(/\/order-confirmation/);
    const orderNumber = await page.textContent('[data-testid="order-number"]');
    expect(orderNumber).toMatch(/ORD-\d+/);
  });
 
  test('should show error when payment fails', async ({ page }) => {
    await page.goto('https://example.com/checkout');
    await page.fill('input[name="address"]', '123 Main Street');
 
    // 不正なカード番号を入力
    const frameHandle = await page.$('iframe[title="Payment form"]');
    const paymentFrame = await frameHandle.contentFrame();
    await paymentFrame.fill('input[name="cardnumber"]', '0000000000000000');
 
    await page.click('button:has-text("Place Order")');
 
    // エラーメッセージを確認
    const error = await page.textContent('[data-testid="payment-error"]');
    expect(error).toContain('Payment failed');
  });
 
  test('should handle network timeouts gracefully', async ({ page }) => {
    await page.route('**/api/checkout', route => route.abort('timedout'));
 
    await page.goto('https://example.com/checkout');
    await page.click('button:has-text("Place Order")');
 
    // タイムアウトエラーを期待
    const errorMessage = await page.waitForSelector('[data-testid="error-message"]');
    expect(errorMessage).toBeTruthy();
  });
});

ミューテーションテストの概念

ミューテーションテストは、テスト品質を評価するための高度な手法です。ソースコードに意図的な変更(ミューテーション)を加え、それがテストで検出されるかを検証します。

Antigravity AI は、Stryker などのミューテーションテストツールと連携して、以下を実現できます:

  • テスト有効性スコア — テストがどれだけのミューテーションを検出したか
  • カバレッジギャップの特定 — テストされていないコード経路
  • テスト改善提案 — 検出漏れのミューテーションに対する新規テストケース
// ミューテーション検出例
// 元のコード
function isEligibleForDiscount(age: number, purchaseAmount: number): boolean {
  return age >= 65 && purchaseAmount > 100;
}
 
// ミューテーション 1: >= を > に変更
// テストで検出されるべき: expect(isEligibleForDiscount(65, 150)).toBe(true)
 
// ミューテーション 2: && を || に変更
// テストで検出されるべき: expect(isEligibleForDiscount(65, 50)).toBe(false)

Antigravity エージェント活用のベストプラクティス

  1. 段階的なテスト設計 — 単体テスト → 統合テスト → E2E テストの順序で進める
  2. 明確なプロンプト — テスト対象、カバレッジ目標、使用フレームワークを具体的に指定
  3. 継続的な検証 — 生成されたテストを実行・検証し、フィードバックループを確立
  4. カバレッジ監視 — CI/CD パイプラインにカバレッジ測定を組み込む

まとめ

Antigravity AI を活用することで、テスト駆動開発(TDD)のサイクルを大幅に短縮できます。単体テストの高速生成、統合テストのモック戦略の自動化、E2E テストの詳細シナリオ設計すべてが、AI の支援により効率化されます。

テスト品質とカバレッジを同時に高めることで、より信頼性の高いソフトウェア開発が可能になります。ぜひ Antigravity AI を試してみてください。

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Tips & 活用術2026-04-01
Antigravity × TDD実践マスター:AIとペアでバグゼロを実現する開発戦略
AntigravityとTDD(テスト駆動開発)を組み合わせた実践的な開発戦略を解説。Jest・Vitest・Playwright・Detoxを使った自動テスト生成からCI/CDまで、バグゼロを目指すプロ向け完全ガイド。
Editor View2026-07-17
パスの空白ひとつで、エージェントのコマンド9形が「0件・成功」を返しました
ワークスペース名に空白が入っているだけで、エージェントの生成したコマンドは静かに別の場所へ届きます。未引用パス11形の実測と、cd の一行に境界を閉じる入口スクリプトの実装まで。
Editor View2026-07-16
4,000行のログをエージェントに渡す三つの道 — 貼り付け・.txt 添付・@ 参照を測り分ける
v2.3.0 でプレーンテキスト添付に対応しました。長いログをエージェントへ渡す手段が三つに増えたことで、どれをいつ選ぶかという新しい迷いが生まれています。切り出し・計測・判断フローを実装込みで整理しました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →