testing について
DBHubのコントリビューター向けに、Vitestのユニットテストと統合テストを扱うスキルです。コマンド、テスト構成、データベース用フィクスチャ、Dockerを使う統合テストのトラブルシューティングを説明します。
主な機能
- 01ユニット・統合テストの実行
- 02ファイル名やテスト名での絞り込み
- 03Vitestのプロジェクトとファイル規約
- 04Testcontainersによるコネクタテスト
- 05Dockerテストの問題調査
活用シーン
- 01DockerなしでDBHubのユニットテストを実行
- 02統合テストでデータベースコネクタを確認
- 03共有テストスイートを使ってコネクタテストを追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ bytebase/ dbhub --skill testingインストール後、Claude Code で/testingを入力して読み込まれたか確認します。
詳細
テストスキル
このスキルでは、DBHub プロジェクトでのテストの実行、作成、トラブルシューティングを支援します。
テストコマンド
pnpm test # Run all tests (unit + integration)
pnpm test:unit # Unit tests only (no Docker needed)
pnpm test:watch # Interactive watch mode
pnpm test:integration # Integration tests only (requires Docker)
特定のテストファイルを実行します:
pnpm test src/connectors/__tests__/postgres.integration.test.ts
pnpm test src/utils/__tests__/allowed-keywords.test.ts
名前のパターンに一致するテストを実行します:
pnpm test -- --testNamePattern="PostgreSQL"
デバッグ用の詳細な出力:
pnpm test:integration --reporter=verbose
テストアーキテクチャ
vitest.config.ts では、次の2つのプロジェクトが設定されています:
- unit:ファイル名に
*integration*を含むものを除く、すべての*.test.tsファイル - integration:
*integration*.test.tsファイルのみ
つまり、命名規則が重要です。統合テストが正しく分類されるには、ファイル名に integration を含める必要があります。
テストファイルの場所
ユニットテスト(約20ファイル、Docker 不要):
src/utils/__tests__/— ユーティリティ関数のテスト(SQL の解析、DSN の難読化、SSH 設定、許可キーワード、識別子の引用、パラメーターのマッピング、行数制限、安全な URL、設定ウォッチャー、AWS RDS 署名者)src/tools/__tests__/— ツールハンドラーのテスト(execute-sql、search-objects、custom-tool-handler)src/config/__tests__/— 設定のテスト(環境変数の解析、TOML の読み込み)src/connectors/__tests__/— コネクターのユニットテスト(dsn-parser、manager)src/requests/__tests__/— リクエストストアのテスト
統合テスト(約11ファイル、Docker が必要):
src/connectors/__tests__/postgres.integration.test.tssrc/connectors/__tests__/mysql.integration.test.tssrc/connectors/__tests__/mariadb.integration.test.tssrc/connectors/__tests__/sqlserver.integration.test.tssrc/connectors/__tests__/oracle.integration.test.tssrc/connectors/__tests__/sqlite.integration.test.tssrc/connectors/__tests__/postgres-ssh.integration.test.tssrc/connectors/__tests__/multi-sqlite-sources.integration.test.tssrc/__tests__/json-rpc-integration.test.tssrc/api/__tests__/sources.integration.test.tssrc/api/__tests__/requests.integration.test.tssrc/config/__tests__/ssh-config-integration.test.ts
IntegrationTestBase
データベースコネクターの統合テストは、src/connectors/__tests__/shared/integration-test-base.ts の IntegrationTestBase<TContainer> を継承します。この抽象クラスには、次の機能があります。
- ライフサイクル:
beforeAllでコンテナーを起動(タイムアウト120秒)→ 接続 → テストデータをセットアップ → テストを実行 →afterAllでクリーンアップ - 共有テストスイート:
createConnectionTests()、createSchemaTests()、createTableTests()、createSQLExecutionTests()、createStoredProcedureTests()、createCommentTests()、createErrorHandlingTests() - 標準テストデータ:
usersテーブル(id、name、email、age)+ordersテーブル(id、user_id、amount)+test_schema.products
新しいデータベースコネクターのテストを追加するには、このクラスを継承し、次を実装します。
createContainer()— Testcontainers インスタンスを起動しますcreateConnector()— データベースコネクターを作成しますsetupTestData(connector)— テストテーブルにデータを入力します
テストフィクスチャ
src/__fixtures__/ にあります。
helpers.ts— ユーティリティ:fixtureTomlPath()、loadFixtureConfig()、setupManagerWithFixture()toml/multi-sqlite.toml— 3つのインメモリ SQLite データベース(database_a、database_b、database_c)toml/readonly-maxrows.toml— readonly/max_rows ツール設定を持つソース
使用方法:
import { setupManagerWithFixture, FIXTURES } from '../../__fixtures__/helpers.js';
const manager = await setupManagerWithFixture(FIXTURES.MULTI_SQLITE);
// ... test ...
await manager.disconnect();
モックのパターン
ユニットテストでは vitest のモックを使用します。
vi.mock('../../connectors/manager.js'); // Mock ConnectorManager
vi.mocked(ConnectorManager.getCurrentConnector).mockReturnValue(mockConnector);
SSH トンネルのテストでは、設定の受け渡しをテストしつつ実際の SSH 接続を避けるため、SSHTunnel.prototype.establish をモックします。
統合テスト
統合テストでは、Docker 内で実際のデータベースインスタンスを実行するために Testcontainers を使用します。
前提条件
統合テストを実行する前に、次を確認してください。
- Docker がインストールされ、実行中であること:
docker ps - Docker に十分なメモリがあること(特に SQL Server では4GB以上を推奨)
- Docker イメージを取得するためのネットワークアクセスがあること
データベースイメージ
| データベース | イメージ | 備考 |
|---|---|---|
| PostgreSQL | postgres:15-alpine | 起動が高速 |
| MySQL | @testcontainers/mysql | IAM 認証のテストに対応 |
| MariaDB | @testcontainers/mariadb | IAM 認証のテストに対応 |
| SQL Server | @testcontainers/mssqlserver | 起動が遅い(3~5 分)。4GB 以上の RAM が必要 |
| Oracle | @testcontainers/oraclefree (gvenzl/oracle-free:23-slim-faststart) | ダウンロードは約 1.2GB、起動に 1~2 分。2GB 以上の RAM が必要 |
| SQLite | コンテナー不要 | インメモリまたはファイルベース |
トラブルシューティング
コンテナーの起動失敗
docker ps # Verify Docker is running
docker system df # Check disk space
docker pull postgres:15-alpine # Manually pull images
SQL Server のタイムアウト
SQL Server のコンテナーは起動に最も時間がかかります(3~5 分)。個別に実行し、Docker に 4GB 以上のメモリが割り当てられていることを確認してください。
pnpm test src/connectors/__tests__/sqlserver.integration.test.ts
テストの分離に関する問題
各統合テストは、それぞれのコンテナーのライフサイクルを管理します。コンテナーが残ってしまう場合は、クリーンアップしてください。
docker ps -a | grep testcontainers # Find leaked containers
docker container prune # Clean up stopped containers
afterAll での「Hook timed out in 10000ms」
すべてのテストが成功していても、afterAll でスイートが失敗と判定されることがあります(CI で MariaDB および postgres-ssh にて発生)。ティアダウンでは container.stop() を実行します。これは docker stop -t 0 の後に docker rm -v(データボリュームの削除)を実行します。Oracle または SQL Server のイメージを同時にプル/展開している共有 Docker デーモンでは、この削除に Vitest のデフォルトのフックタイムアウトである 10 秒を超える場合があります。このため、統合テストのプロジェクトでは vitest.config.ts に hookTimeout: 60_000 を設定しています。afterAll にこれより短いタイムアウトを渡さないでください。また、独自のティアダウンを行うスイートを追加する場合は、Vitest のデフォルトではなく、プロジェクトのデフォルト設定を使用してください。
CI の失敗
CI ワークフロー(.github/workflows/run-tests.yml)では、PR イベント時に単体テストと統合テストを別々の並列ジョブとして実行します。単体テストには Docker は不要です。統合テストでは、まず Docker が利用可能かどうかを確認します。失敗したジョブを確認してください。
新しいテストの追加
単体テスト:src/{module}/__tests__/{name}.test.ts を作成します。pnpm test:unit で自動実行されます。
統合テスト:src/{module}/__tests__/{name}.integration.test.ts を作成します。ファイル名に integration を含めると、pnpm test:integration の実行対象になります。
新しいコネクターのテスト:IntegrationTestBase を継承し、3 つの抽象メソッドを実装して、共有テストスイートのメソッドを呼び出します。