kickflow Tech Blog

株式会社kickflowのプロダクト開発本部によるブログ

テスト管理ツール「KickRail」を内製した話

クマノミは自分の住処にするイソギンチャクを選び、共生関係を育てる
クマノミは自分の住処にするイソギンチャクを選び、共生関係を育てる

こんにちは、kickflow QAチームの川村です。

QAチームで使っていたテスト管理ツールを、Qaseから自作の KickRail に乗り換えました。
3日でアルファ版を立ち上げ、その10日ほど後にはQaseから完全リプレイス。
約6万件のテストケースが新しい住処に引っ越し、いまも安定稼働しています。

本記事では、なぜ作ったか、何をどう作ったか、そしてMCPファースト設計でAIエージェントから直接操作する仕組みを紹介します。

課題:Qase運用で見えてきた壁

kickflow QAチームでは、これまでQaseをテスト管理ツールとして運用していました。
TestRailからQaseに移行した時点ではコスト面・UX面の不満は解消され、しばらく快適に運用していました(当時の経緯は以前のツールスタック紹介記事に書いています)。

しかし、運用を続けるうちに、kickflowの規模や運用スタイルに合わない部分が見えてきました。

1. テストケースの規模拡大に運用が追いつかない

kickflowのテストケースは数万件規模にまで増えています。
この規模になると、画面遷移や複数ケースの一括操作のレスポンスが私たちの運用テンポに合わなくなり、レビューやリファクタリングの手が止まることが増えてきました。

2. AI/MCP連携を独自ワークフローに深く組み込みたい

kickflowには AI 1st というバリューがあり、開発もQAもAIエージェント前提でフローを組んでいます。

note.com

特に、Claude DesktopやClaude CodeからMCP経由でテスト管理ツールを操作できれば、テスト設計のSkillから直接ケース投入、テスト実施のSkillから直接結果記録ができ、QAパイプラインがシームレスにつながります。

Qase MCPも存在するため標準的な操作はカバーできますが、私たちが本当に必要としていたのは「テスト設計 → 実施 → エビデンス記録」をSkillから一気通貫で叩ける最小セットと、運用しながら欲しくなったツールを自分たちで自由に足し引きできる自由度でした。
汎用的なSaaSのMCPに合わせるより、自分たちのSkill運用に必要なツールを自前で持つほうが速い、という判断です。

3. 開発者レビュー用の細かい改善に手が届かない

kickflowでは、QAが設計したテストケースを開発者にもレビューしてもらいます。
そのとき、「レビュー中に気になったケースをSlackやGitHub Issueにさっと共有したい」「バグチケット起票用にケース名をそのままコピーしたい」といった、レビュワー(viewerロール)ならではの細かな要望が出てきます。
SaaSでは、こうした自分たち固有のレビューフローに合わせた小さな改善のほとんどに手が届きません。

解決策:KickRail を内製

3つの課題を根本から解消するため、kickflowのQA運用にフィットするテスト管理ツールを内製することにしました。
名付けて KickRail。「Qase風のUI/データモデルを継承しつつ、MCPファーストで設計し、kickflowのQAワークフローに細かく合わせる」を方針に置きました。

開発から運用開始までのタイムライン

時期 やったこと
2026年2月下旬 3日でアルファ版を組み上げ、QAチームに配布してフィードバックを募集
2月下旬〜3月上旬 フィードバックを受けてUIとAPIを修正
3月上旬 Qaseから完全リプレイス、運用開始(約6万件のテストケースを移行)
3月〜4月 細かいバグ修正・機能追加・パフォーマンス改善

アルファ版を配布してから10日ほどで本番移行まで持っていけました。
3日でα版を出せたのは、QaseのUI/データモデルを下敷きにして仕様を固める手間を省きつつ、Claude CodeをフルにドライブしてUIとAPIを一気に生成していったからです。

実際のテストケース管理画面とテストラン画面はこんな雰囲気です。

KickRailのテストケース管理画面
テストケース管理画面:左にスイートツリー、中央にケース一覧、右に詳細

KickRailのテストラン画面
テストラン画面:ケースごとに結果ステータスを記録していく

アーキテクチャと技術スタック

KickRailは「Web UI + REST API + MCPサーバー」の3つのレイヤーで構成しています。

レイヤー 技術
Backend Go + chi router
Frontend React 19 + TypeScript + Vite + Tailwind CSS v4
Database PostgreSQL 15(ltree でスイート階層、pg_trgm で全文検索)
State Zustand(認証・テーマ)+ TanStack Query(サーバー状態)
Auth JWT + Personal Access Tokens
MCP TypeScript + @modelcontextprotocol/sdk
Deploy Docker + Google Cloud Run + Cloud SQL

技術選定で最優先したのはパフォーマンスです。
数万件規模のケースを抱えても軽快に表示・検索できることを最優先に、Goと、階層構造・全文検索に強いPostgreSQLを選びました。

graph TD
    subgraph clients[クライアント]
        UI[Web UI<br/>React + Vite]
        CC[Claude Desktop / Claude Code]
        SK[QA Skill<br/>テスト設計 / 実施 など]
    end

    subgraph kickrail[KickRail]
        API[REST API<br/>Go + chi]
        MCP[MCP Server<br/>TypeScript SDK]
        DB[(PostgreSQL<br/>ltree + pg_trgm)]
    end

    UI -->|JWT| API
    CC -->|MCP / PAT| MCP
    SK -->|MCP / PAT| MCP
    MCP -->|REST / PAT| API
    API --> DB

ポイントは、MCPサーバーが内部的にREST APIを叩くだけのシンプルな層になっていることです。
UIもAIエージェントも同じREST APIを通るため、振る舞いに差が生まれません。

階層スイートはPostgreSQLのltreeで管理

KickRailのスイートは「機能追加・改善 > ホワイトボックス観点 > 機能性テスト」のように入れ子になります。
これを ltree 型で持っておくと、子孫スイートの一括取得や階層の付け替えがインデックス付きで高速に行えます。

ドラッグ&ドロップでスイートを別の親に移動する操作も、ltreeのパス書き換え1発で済むため、コードの見通しがすっきりしました。

MCPファースト設計のキモ

KickRailで一番こだわったのは、MCPを後付けの拡張点ではなく、最初から中核に据えたことです。

提供しているMCPツール

Claude Desktop / Claude Codeから呼び出せるツールは、現在16個です。

領域 ツール
スイート get_suites / create_suite / delete_suite
ケース get_test_cases / create_test_case / create_test_cases_in_bulk / update_test_case / delete_test_case / delete_test_cases_in_bulk
テストラン get_test_runs / create_test_run
テスト結果 get_test_run_results / update_test_results
エビデンス upload_result_attachment(スクリーンショット等を添付)
APIテスト get_api_test_runs / get_api_test_items(Postman由来のAPIテスト結果を参照)

「テスト設計から実施までQAエンジニアが触る操作」を、ほぼ全て網羅しています。
リリース当初は11個でしたが、運用しながら一括削除やAPIテスト結果の参照など、必要になったものを足してきました。MCPツール自体を自分たちのペースで増やせるのが、内製ならではの強みです。

Qase MCPとの住み分け

参考までに、Qase MCPとKickRail MCPの守備範囲を比べると、それぞれの設計思想がよく見えてきます。

観点 Qase MCP KickRail MCP
カバー範囲 欠陥管理・マイルストーン・共有ステップなど広範 テスト設計〜実施〜エビデンスに集中
検索 Qase Query Language(強力なクエリ言語) タイトル検索+スイート・優先度フィルタ
エビデンス添付 スクリーンショット等を添付可能
独自拡張 SaaSの提供範囲 Postman由来のAPIテスト結果参照など自由に追加

Qase MCPは汎用的で守備範囲が広く、多くのチームにとってはこちらが最適です。
一方KickRailは、自分たちのSkill運用に必要なツールだけを持ち、足りなければすぐ足す。この「特化と自由度」に振り切っています。

設定例

KickRailの管理画面でPersonal Access Token(PAT)を発行し、.mcp.json に登録するだけです。

{
  "mcpServers": {
    "kickrail": {
      "command": "npx",
      "args": ["-y", "tsx", "<path-to>/kickrail/mcp/src/index.ts"],
      "env": {
        "KICKRAIL_URL": "https://<your-kickrail-url>",
        "KICKRAIL_TOKEN": "<your-pat>"
      }
    }
  }
}

これで、QAメンバーがClaude Desktop/Codeから自然言語で

このIssueのテスト観点をKickRailにインポートして

と依頼するだけで、get_suites で親スイートを特定し、create_test_cases_in_bulk で一括登録、というフローが走るようになりました。
テスト観点をKickRailにインポートする import-cases Skillや、現在試験運用中のテスト実施Skillも、このMCPを叩いています(これらのSkillは別の記事で詳しく紹介する予定です)。

Qaseからの移行:全量インポート + 差分同期の二段構え

6万件規模のテストケースを一気にカットオーバーするのは怖いので、二段階で移行しました。

1. 初回:全量インポート(cmd/import

QaseのAPIを叩いてプロジェクト・スイート・ケースを全量取得し、KickRailのスキーマに変換してinsertするGoのCLIを用意。
何度も再実行・rollbackしながら、KickRail側のスキーマや移行ロジックを詰めていきました。

2. 並行運用期:差分同期バッチ(cmd/sync

完全リプレイスする前の数日間は、Qaseをマスターとして並行運用しました。
その間、Qase側で新規追加や更新があったケース・テストランをKickRailに追従させるため、差分同期CLIを用意。

  • ケース同期: 対象スイート配下のみ取得(数分で完了)
  • ラン同期: 直近30日分のみ(10分程度)

リプレイス当日は、最後のsyncを流してQaseのアクセスを切るだけ。
移行中の入力ロストを発生させずに、6万件のケースを新しい住処に引っ越しできました。

結果

定量・定性の両面で、移行前に感じていた課題がほぼ解消されました。

項目 Before After(KickRail)
動作のレスポンス 規模拡大とともに重くなりがち 6万件規模でもスイート展開・検索が軽快
MCP/AI連携 自作ブリッジで毎回保守 KickRail MCPでClaude Desktop / Codeから直接操作
カスタマイズ SaaSの範囲内 viewer用コピー機能・ディープリンクなど自由に追加
ライセンス費用 SaaSライセンス分 限りなくゼロ(Cloud Runの微小な使用料のみ)

そして何より、設計フェーズも実施フェーズも、AIエージェントがKickRailに直接書き込めるようになったことが大きな変化です。
人間が手作業で「Claudeが作った観点をKickRailに入力する」というブリッジ作業が消えました。

チームの手で育つプロダクトへ

立ち上げこそ私が一人で進めましたが、運用が始まってからはチームの共有資産として育っています。

象徴的なのが、CIで実行したテストの結果をKickRailに自動反映する仕組みを、別のQAメンバーが追加開発してくれたことです。
Postmanで回しているAPIテストと、Playwrightで回しているE2Eテストについて、nightly実行の結果(pass / fail / skipなど)をKickRailに取り込み、専用画面で一覧・可視化できるようになりました。
これまでGitHub Actionsのログを追わないと分からなかった自動テストの結果が、テスト管理ツール上で日々の推移とともに確認できます。

APIテスト結果の一覧画面
PostmanのAPIテスト結果サマリーをKickRailで可視化
APIテスト結果の詳細画面
PostmanのAPIテストのアサーション結果をKickRailで可視化

PlaywrightのE2Eテスト結果一覧
PlaywrightのE2Eテスト結果(nightly実行)をKickRailで一覧化
PlaywrightのE2Eテスト結果詳細
PlaywrightのE2Eテスト結果(nightly実行)をKickRailで可視化

内製ツールの良さは、欲しい人が欲しい機能を自分の手で足せることです。
冒頭の課題で挙げた「ケース名のワンクリックコピー」や「ケースIDのディープリンク(SlackやGitHub Issueに貼るとリンクになる)」も、テストケースをレビューする開発者から実際に要望が届いて追加した機能です。
SaaSなら要望を出して実装を待つところを、内製なら自分たちですぐ形にできます。

私が用意したのはあくまで土台で、そこにチームメンバーが各自の課題感で機能を積み上げていく。
プロダクトとしての広がりが、いい形で回り始めています。

今後の展望

KickRailは現在も日々改善が続いています。
今後は以下のような方向で広げていく予定です。

  • テスト実施AI化との深いつながり: AIがブラウザを操作して実施したテスト結果を、その場でKickRailに記録(スクリーンショット添付込み)
  • AIによるテストケースの棚卸し: 6万件規模まで膨らんだケースをAIで横断的に見渡し、重複や陳腐化したケースを検知して整理する
  • メトリクスの可視化: ラン全体のpass率・flaky率・テスト効率を、運用判断に直接使える形でダッシュボード化

まとめ

QA運用に必要な機能だけに絞り、最初からMCPファーストで設計することで、3日でアルファ版・2週間でQaseリプレイスというスピードで内製テスト管理ツールを立ち上げられました。
SaaSをやめる選択は重い決断ですが、AIエージェントとシームレスに連携できるQA基盤は、今のkickflowの開発スピードに不可欠でした。

自分たちの仕事のリズムに合うツールを自前で持ち、必要に応じて育てていけることが、内製化の一番のメリットだと感じています。

careers.kickflow.co.jp