こんにちは、junya です。前回に引き続き、QAツール開発の第3回をお届けします。
- LOVOT QA効率化の話:半自動テストのすすめ
- LOVOT QA効率化の話:LOVOT QA Appのアーキテクチャ
- LOVOT QA効率化の話:シニア・ジュニア・AI最強説(本記事)
今回は、QAツール開発で、インターンの方とAI(主に Claude Code)を使って開発したら、生産性がバク上がりしたというお話です。
シニア+ジュニア+AI 最強説
はじめに結論から書きますが、シニア+ジュニア+AIは最強です。互いに相補的な関係があるからです。
- シニア
- 技術選定やアーキテクチャ設計
- 難しめのタスクの実装
- ジュニア
- 仲間とコミュニケーションできる
- 柔軟な動作確認など、AIにできないことができる
- AI
- 技術に詳しい
- 実装が速い
これによって、シニアが1つの難しいタスクに取り組んでいる間に、ジュニア+AIで、平易だけど大切なタスクを5つ解決できます。そして、意外とこの「平易なタスク」の範囲は広く、要件や実装方針をシニアが明示できるものは、だいたいジュニア+AIで実装可能です。
では具体的に、QAツール開発プロジェクトで何が起きたか、順番に見ていきましょう。
関係者のご紹介
- シニア わたし。業務プログラミング歴22年。3月からClaude Codeにどっぷりハマり、2週間でQAツールの基本機能を実装しました。
- ジュニア 公的機関から出向のインターン生。社会人3年目。理系大学出身ですが、業務プログラミング経験はありません。数学オリンピック、謎解きが大好きで地頭が良い方です。
- AI
Claude Code を開発で利用しつつ、何でもまずは Gemini に聞いてみる、という使い方です。Claude Code は
devcontainer
で動かしていました。途中から Devin も活用しました。
1ヶ月間の成果
ジュニアのインターン生が来てから、1ヶ月間での彼女の成果はこちらです。
- 期間: 22日間
- PR: マージ済みPR 30個
実装機能:
- UI/UX改善
- 自動テスト関数引数の表示改善
- 画面レイアウト調整(全幅利用、レスポンシブ表示等)
- 入力欄の末尾空白除去
- リロードボタン追加
- 添付/キャプチャ画像のモーダル表示
- ブラウザタブ用faviconアイコン作成
- 機能追加・連携強化
- Slack連携機能
- スマホ画面Inspect機能
- テスト対象機体の誤設定時の警告機能
- LOVOTリモート接続機能
- 自動テスト支援関数の実装
- 画面一覧表示機能
- モバイル操作(ページ遷移、クリック、スワイプ、要素検証など)
これらを、残業なし、他のタスクもやりながら達成しました。
なお、その間に私は、彼女からの質問に答えたり、PRを見てアドバイスをしたり、AIを活用するコツの情報交換などしながら、アプリケーションのElectron化や、添付ファイルの仕組み、Poco agent の nuitka
ビルドなどを実装しました。
うまくいった秘訣
うまくいった秘訣がいくつかあるので、ご紹介します。
新規の社内向けツール
1つは、開発対象が新規の社内向けツールだったことです。新規ツールということで、平易だけど重要な、小さな開発要件がたくさんあり、AIコーディングにぴったりでした。また、社内向けツールということで、デザインや機能の自由度が高かったことも大きいです。Devcontainer
devcontainer
の開発環境を用意しておいたのが便利でした。IDE(GoLand でしたが、VSCodeも可能)をインストールして Docker を入れれば、devcontainer
の立ち上げだけで環境が出来上がります。セキュリティリスクも低いです。 今回の実習では、2日目の午前中には環境構築が完了し、2日目の午後から1つ目のタスクのペアワークができました。参考までに、利用した devcontainer 設定を共有します。Microsoft のベースイメージと、Claude Code の feature ファイルを利用するのがポイントです。
// .devcontainer/devcontainer.json { // Dev Containerの表示名(例) "name": "TS/Go Claude Code Dev Container (GoLand)", // ベースとなるイメージ。Microsoft提供のUbuntu 24.04ベースイメージを使用。 // デフォルトで 'vscode' ユーザー (UID/GID 1000) と基本的な開発ツールが含まれます。 "image": "mcr.microsoft.com/vscode/devcontainers/base:ubuntu-24.04", // --- Dev Container Features: 追加のツールやランタイムを簡単に導入 --- "features": { // Claude Code 連携機能 (Anthropic 提供) "ghcr.io/anthropics/devcontainer-features/claude-code:latest": {}, // Bun ランタイム (コミュニティ提供のfeatureを使用) "ghcr.io/prulloac/devcontainer-features/bun:latest": { "version": "latest" // または特定のバージョンを指定 }, // Go 言語環境 "ghcr.io/devcontainers/features/go:1": { "version": "latest" // または特定のバージョンを指定 }, // Node.js 環境 (LTS版を推奨) "ghcr.io/devcontainers/features/node:1": { "version": "lts" }, // --- 開発補助ツール --- // aqua: 開発ツールのバージョン管理 "ghcr.io/aquaproj/devcontainer-features/aqua-installer:0.1.3": { "aqua_version": "v2.51.2" // 使用するaquaのバージョン }, // direnv: ディレクトリごとの環境変数管理 "ghcr.io/devcontainers-community/features/direnv": {}, // GitHub CLI: GitHub操作の効率化 "ghcr.io/devcontainers/features/github-cli:1": {}, // 共通ユーティリティ (Zshの導入とデフォルト設定など) // ベースイメージの 'vscode' ユーザーが使用されるため、ユーザー作成関連の設定は基本的に不要です。 // Git設定の継承など、便利な機能も含まれます。 "ghcr.io/devcontainers/features/common-utils:2": { "installZsh": "true", // Zshをインストール "configureZshAsDefaultShell": "true", // Zshをデフォルトシェルに設定 "installOhMyZsh": "true", // Oh My Zshをインストール (任意) "installOhMyZshConfig": "true", // Oh My Zshの設定を導入 (任意) "upgradePackages": "false", // コンテナビルド時のパッケージアップグレードはスキップ (任意) "configureGpg": "false" // GPGキーの設定は行わない (任意) } }, // ホストマシンのファイルをコンテナ内にマウントする設定 "mounts": [ // ホストの .gitconfig をコンテナ内の 'vscode' ユーザーのホームに読み取り専用でマウント // これにより、ホスト側のGitユーザー設定をコンテナ内で利用できます。 // readonly設定は、コンテナ内からホストの設定ファイルを誤って変更しないために強く推奨されます。 "type=bind,source=${localEnv:HOME}/.gitconfig,target=/home/vscode/.gitconfig,readonly" // 他にもマウントしたいファイルやディレクトリがあればここに追加します。 // 例: ホストのSSH鍵をコンテナにマウントして、プライベートリポジトリへのアクセスなどに使用する場合 // "type=bind,source=${localEnv:HOME}/.ssh,target=/home/vscode/.ssh,readonly" ], // 特定のネットワーク機能が必要な場合のDocker実行時引数 (例: Claude Codeの特定の機能やデバッグ時) // 通常はコメントアウトしておき、必要な場合のみ有効化します。 // "runArgs": [ // "--cap-add=NET_ADMIN", // ネットワークインターフェースの管理権限 // "--cap-add=NET_RAW" // RAWソケットへのアクセス許可 // ], // コンテナ作成「後」に実行したいカスタムコマンド // 例: プロジェクト固有のセットアップスクリプトを実行 "postCreateCommand": "chmod +x .devcontainer/setup.sh && .devcontainer/setup.sh", // コンテナ内で使用するユーザーの指定 // この設定を省略すると、ベースイメージのデフォルトユーザー ('vscode') が自動的に使用されます。 // "remoteUser": "vscode", // 明示的に指定することも可能です。 // --- IDE固有のカスタマイズ設定 (ここではJetBrains GoLandの例) --- "customizations": { "jetbrains": { // GoLandがGo SDKを自動検出できない場合にパスを指定 (通常は自動検出されるため不要) // "goSdkPath": "/usr/local/go/bin/go" // GoLandにインストール推奨のプラグインリスト (例) "plugins": [ "com.github.biomejs.intellijbiome", "com.github.copilot", "com.github.shiraji.findpullrequest", "com.intellij.tailwindcss", "intellij.nextjs", "intellij.vitejs", "org.toml.lang", "PythonCore" // Pythonサポートが必要な場合 ] } // VSCode固有の設定は "vscode": { ... } のように記述します。 }, // --- コンテナ内の環境変数設定 (オプション) --- "containerEnv": { // Go Modules Proxyの設定 (Goプロジェクトで必要に応じて設定) "GOPROXY": "direct", // direct以外に、プロキシサーバーを指定することも可能 // プライベートリポジトリへのアクセス設定 (自社のリポジトリなどに合わせて変更) "GOPRIVATE": "github.com/your-repo" } }
#!/bin/bash # .devcontainer/setup.sh # 日本語ロケールのインストールと設定 sudo apt-get update sudo apt-get install -y --no-install-recommends locales language-pack-ja sudo locale-gen ja_JP.UTF-8 sudo update-locale LANG=ja_JP.UTF-8 # プロファイルにロケール設定を追加 echo 'export LANG=ja_JP.UTF-8' | sudo tee -a /etc/profile.d/locale.sh echo 'export LC_ALL=ja_JP.UTF-8' | sudo tee -a /etc/profile.d/locale.sh ## Claudeファイアウォール初期化 #sudo /usr/local/bin/init-firewall.sh # aquaのパスを各シェルの設定ファイルに追加 echo 'export PATH="/home/vscode/.local/share/aquaproj-aqua/bin:$PATH"' >> ~/.bashrc echo 'export PATH="/home/vscode/.local/share/aquaproj-aqua/bin:$PATH"' >> ~/.zshrc
Claude Code の使い方
普段の実装も、基本、このやり方で実装しています。- Claude と壁打ちして、実装方針を決める(コードはまだ書かせない)
- 実装方針をチェックリストとともに、Markdownに書かせる
- それを元にClaudeのコードを書かせる
コードの配置や利用ライブラリなど、提出されたコードがシニアの実装意図と異なる場合は、シニアからジュニアに、PRや口頭やチャットでフィードバックしました。
ステップに分解する
- スマホのスナップショットをPocoでキャプチャして、
- Poco agent が仲介し、
- TypeScript で受け取って画面に表示
というような、やや複雑なタスクの場合、
- まずは、スマホのスクリーンショットだけを取得してファイル保存するスクリプトをClaudeに実装させて
- 次に、APIを叩いてスクショ撮るスクリプト書かせて
などと段階を踏んでAIに実装をさせるといいよ、とアドバイスしました。ステップを踏めば、どこで躓いたかがわかり、ジュニアでも自身で問題解決できます。
検証用スクリプトを書く
前項の「ステップに分解する」と関係しますが、いきなり機能をアプリケーションに組み込むのではなく、「スクショを撮るスクリプト」のような単体スクリプトやテストをAIに書かせると、実装がスムーズになりました。難しいものは巻き取る
どうしても難しそうなものは、巻き取ったり、保留したりしました。今回の場合、録画機能は実装に詰まったので、深追いせずに保留して他のものを進めてもらいました。後で自分の方で対応します。困ったときはペアワーク
ジュニアがAIとの対話で行き詰まったり、より複雑な実装の理解が必要な際には、シニアとジュニアでペアワークを行い、一緒に問題解決や仕上げを行いました。これにより、知識移転もスムーズに進みました。スタイリングはAIに任せる
社内ツールということもあり、スタイリング(Tailwind CSS)は、はじめの大枠だけ整備して、あとは原則としてレビュー対象とせず、AIの実装をそのまま信じると割り切りました。うまくいかないときはゼロからやり直す
試行錯誤を進めると、Claude が堂々巡りしてしまうことがあります。そういうときは、一度それを捨てて、改めて必要な条件を伝えて実装方針を作り直し、コードを一から書き直させていました。これ結構、大切です。
まとめ
以上、シニア+ジュニア+AIで生産性が非常に高くなった事例をご紹介しました。 AIの足りないところを人間が補い、技術面をAIが担当し、難しい部分をシニアが巻き取ることで、相補的に生産性を上げることができます。
いろいろチャレンジしていて楽しい職場なので、よかったら開発チームに参加しませんか?
学生さん向けには、サマーインターンシップも開催しますので、是非ご応募ください。