mcpField
Q
qe-database-testing

qe-database-testing

github.com/proffesor-for-testingテスト・品質51982 回インストール今日更新
リポジトリ

qe-database-testing について

qe-database-testing は、スキーマ、データ整合性、マイグレーション、トランザクション、クエリ性能を検証するテストスキルです。開発者やテスター向けに、可逆なマイグレーションと並行トランザクションの確認方法を示します。

主な機能

  1. 01テーブル、列、制約の検証
  2. 02一意性、外部キー、データ整合性の確認
  3. 03マイグレーション実行とロールバックのテスト
  4. 04トランザクション分離と ACID 特性の検証
  5. 05クエリ性能とインデックス利用の測定

活用シーン

  1. 01新規テーブルやデータベーススキーマの検証
  2. 02データを保持してマイグレーションを戻せるか確認
  3. 03エラー発生時のトランザクションロールバックをテスト
  4. 04クエリ性能の問題を調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/proffesor-for-testing/agentic-qe --skill qe-database-testing

インストール後、Claude Code で/qe-database-testingを入力して読み込まれたか確認します。

詳細

データベーステスト

<default_to_action> データベース操作をテストする場合:

  1. スキーマを検証します(テーブル、列、制約が想定どおり存在すること)
  2. データの整合性をテストします(一意制約、外部キー制約、CHECK 制約)
  3. マイグレーションを確認します(適用が成功すること、ロールバックが成功すること、データが保持されること)
  4. トランザクションの分離性をチェックします(ACID 特性、並行アクセス)
  5. クエリのパフォーマンスを測定します(インデックスが使用されていること、実行時間)

データベーステストの簡易チェックリスト:

  • スキーマが仕様と一致している
  • 一意制約によって重複が防止される
  • 外部キー制約によって孤立レコードが防止される
  • マイグレーションを元に戻せる
  • エラー時にトランザクションがロールバックされる

成功のための重要な要因:

  • データベースのバグはデータの損失/破損を引き起こします(致命的です)
  • 本番環境の前にステージング環境でマイグレーションをテストします
  • トランザクションテストで並行処理のバグを検出できます </default_to_action>

クイックリファレンスカード

使用する場面
  • 新しいテーブル/スキーマの作成
  • マイグレーションの開発
  • データ整合性の検証
  • クエリパフォーマンスの最適化
データベーステストの種類
種類対象タイミング
スキーマ構造が正しいことテーブル作成時
整合性制約が機能することデータ操作時
マイグレーション適用/ロールバックが機能することスキーマ変更時
トランザクションACID 特性並行アクセス時
パフォーマンスクエリ速度最適化時
ACID 特性
特性テスト対象
原子性すべて成功するか、すべて失敗すること(エラー時にロールバック)
一貫性制約が常に有効であること
分離性並行するトランザクションが互いに干渉しないこと
永続性コミット済みのデータが保持されること

スキーマテスト

test('users table has correct schema', async () => {
  const schema = await db.raw(`
    SELECT column_name, data_type, is_nullable
    FROM information_schema.columns
    WHERE table_name = 'users'
  `);

  expect(schema).toContainEqual({
    column_name: 'id',
    data_type: 'integer',
    is_nullable: 'NO'
  });

  expect(schema).toContainEqual({
    column_name: 'email',
    data_type: 'character varying',
    is_nullable: 'NO'
  });
});

データ整合性テスト

test('email must be unique', async () => {
  await db.users.create({ email: '[email protected]' });

  await expect(
    db.users.create({ email: '[email protected]' })
  ).rejects.toThrow('unique constraint violation');
});

test('foreign key prevents orphaned records', async () => {
  const user = await db.users.create({ email: '[email protected]' });
  await db.orders.create({ userId: user.id, total: 100 });

  await expect(
    db.users.delete({ id: user.id })
  ).rejects.toThrow('foreign key constraint');
});

マイグレーションテスト

test('migration is reversible', async () => {
  await migrate('add-users-table');

  // Table exists after migration
  const tables = await db.raw(`SELECT table_name FROM information_schema.tables`);
  expect(tables.map(t => t.table_name)).toContain('users');

  await rollback('add-users-table');

  // Table gone after rollback
  const tablesAfter = await db.raw(`SELECT table_name FROM information_schema.tables`);
  expect(tablesAfter.map(t => t.table_name)).not.toContain('users');
});

test('migration preserves existing data', async () => {
  await db.users.create({ email: '[email protected]' });

  await migrate('add-age-column');

  const user = await db.users.findOne({ email: '[email protected]' });
  expect(user).toBeDefined();
  expect(user.age).toBeNull(); // New column, null default
});

トランザクションテスト

test('transaction rolls back on error', async () => {
  const initialCount = await db.users.count();

  try {
    await db.transaction(async (trx) => {
      await trx('users').insert({ email: '[email protected]' });
      await trx('users').insert({ email: '[email protected]' });
      throw new Error('Rollback test');
    });
  } catch (error) { /* Expected */ }

  expect(await db.users.count()).toBe(initialCount);
});

test('concurrent transactions isolated', async () => {
  const user = await db.users.create({ balance: 100 });

  // Two concurrent withdrawals (race condition test)
  await Promise.all([
    db.transaction(async (trx) => {
      const current = await trx('users').where({ id: user.id }).first();
      await trx('users').update({ balance: current.balance - 50 });
    }),
    db.transaction(async (trx) => {
      const current = await trx('users').where({ id: user.id }).first();
      await trx('users').update({ balance: current.balance - 50 });
    })
  ]);

  const final = await db.users.findOne({ id: user.id });
  expect(final.balance).toBe(0); // Proper isolation
});

エージェント主導のデータベーステスト

// Generate test data with integrity
await Task("Generate Test Data", {
  schema: 'ecommerce',
  tables: ['users', 'products', 'orders'],
  count: { users: 1000, products: 500, orders: 5000 },
  preserveReferentialIntegrity: true
}, "qe-test-data-architect");

// Test migration safety
await Task("Migration Test", {
  migration: 'add-payment-status-column',
  tests: ['forward', 'rollback', 'data-preservation'],
  environment: 'staging'
}, "qe-test-executor");

エージェント連携のヒント

メモリ名前空間
aqe/database-testing/
├── schema-snapshots/*   - Current schema state
├── migrations/*         - Migration test results
├── integrity/*          - Constraint validation
└── performance/*        - Query benchmarks
フリート連携
const dbFleet = await FleetManager.coordinate({
  strategy: 'database-testing',
  agents: [
    'qe-test-data-architect',  // Generate test data
    'qe-test-executor',        // Run DB tests
    'qe-performance-tester'    // Query performance
  ],
  topology: 'sequential'
});

関連スキル


忘れないでください

データベースのバグは致命的です。 データの損失は復旧できません。破損は気付かれないまま広がります。パフォーマンスの問題は積み重なります。

本番環境の前にマイグレーションをテストします: 適用が成功すること、ロールバックが成功すること、データが保持されること、パフォーマンスが許容範囲であることを確認します。テストしていないマイグレーションをデプロイしてはいけません。

エージェントを使用する場合: qe-test-data-architect は参照整合性を保ちながら、現実的なテストデータを生成します。qe-test-executor は CI/CD でマイグレーションを自動的に検証します。

コメント