やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

Unityプロジェクトでも Claude Code に自走させるワークフロー

最近は Claude Code 中心に使っていて、Unityプロジェクト(といってもゲームでなくUPMパッケージ開発が多い)でもそこそこ安定するワークフローが固まってきました。 一例として紹介します。

目的

紹介するワークフローの目的は次の2点です。

  • できるだけ自律的に、自走させたい
  • レビュー負荷を減らしたい

前提として、すべてこのワークフローを使うのではなく、例えばコードを書きながら探索的に設計したいケースでは*1 従来通りGitHub Copilotのサジェストを使ってTDDで書いています。

また、いわゆる "Vibe Coding" ではなく、実装コードもテストコードもレビューし、保守性を高める修正を入れています。

ワークフロー

次の手順で開発を進めます。

  1. Plan modeで、実装する機能の要件、仕様、一部の実装方法などを伝え、それを一旦ドキュメントに書き出し
  2. ドキュメントをもとにテストケースを作成、ドキュメントに追記
  3. ドキュメントに従って実装。テストファースト(TDDではない)で、テストをパス、Roslynアナライザなどの診断にも対応させて完了

ドキュメントを経由する理由は、チェックポイントとして使うことと、コンテキストウィンドウの圧縮です。 各工程でドキュメント出力したら /clear コマンドなどでコンテキストをクリアしています*2

Claude Codeに限らず、ルールの強制力は弱いのであまり信用していなくて、プロンプトによる指示を重視していました。 Claude Codeにはカスタムコマンド機能があるので、各工程に対応したコマンドファイルを用意して使用しています。

/create-doc コマンド

工程1で要件などを伝え終えた後で(Claude Codeが実装に進もうとするのを止めて)実行します。

これまでの会話内容を仕様書としてファイルに書き出してください。

以下の手順に従ってください。

1. 会話中に、要件(なぜ)、仕様(何を)、設計(どのように)が明確になっているか分析してください。明確でない場合は、このコマンドの実行を中止してください。
2. ファイルに書き出してください。
  - 形式:Markdown
  - 言語:日本語
  - パス:./Documentation/yyyy-mm-dd-subject.md
    - yyyy-mm-dd は現在日付です。
  - セクション:
    - 要件、問題、または動機(適切なものを選択してください)
    - 仕様
    - 設計
3. Git にコミットしてください。

ドキュメント化に必要な情報を伝えきれていれば、ファイルが作られます。 軸になるのは「仕様」の部分ですが、LLMへの指示が目的ですので、ある程度の実装方式まで盛り込むほうが後工程が安定します。

この時点でレビューし、不足情報があれば付け足すなど修正します。 修正は Claude Code に頼んでも、ファイルを直接書き換えても構いません。

/create-test-cases コマンド

/clear 後もしくは新しい会話セッションで入力します。引数に、create-doc で生成したドキュメントファイルパスを渡します。

$ARGUMENTS ファイルの仕様が満たされていることを確認するために必要なテストケースを考え、ファイルに追加してください。

以下の手順に従ってください。

1. 仕様を読み、分析します。明確でない場合は、このコマンドの実行を中止してください。
2. テスト対象の public クラスとメソッドを、統合度の低い順に選択します。
3. カバレッジを考慮したテストケースを導出するために使用するテスト技法(同値分割法、境界値分析、状態遷移テストなど)を選択します。
4. テスト技法を使用して、自然言語でテストケースを作成します。以下の点に注意してください。
  - 連続した ID は作成しないでください。
  - 検証内容を記述します。検証できない場合はテストケースを削除します。
5. テスト対象のすべてのクラスがカバーされるまで、手順 2 から 4 を繰り返します。
6. $ARGUMENTS ファイルにテストケースを追加します。
7. Git にコミットします。

これで、ドキュメントにテストケースが追記されますので、レビューします。 検証しにくく、かつ価値の低いテストケースを挙げられることもあるので、この時点で刈り取っておきます*3

テストケースを見て仕様の不備に気づくことも多いので、その場合は仕様部分も同時に修正したり、問題が大きい場合は revert して前工程に戻ってもいいでしょう。

なお、手順2で結合度の低い順と指示しているのは、逆だと無駄にテストダブルを使ってテストを書こうとするためです。

/implement-code コマンド

/clear 後もしくは新しい会話セッションで入力します。引数に、create-doc で生成したドキュメントファイルパスを渡します。

$ARGUMENTS ファイルの仕様を満たすコードを実装してください。

以下の手順に従ってください。

1. 仕様にテストケースが含まれていない場合は、このコマンドの実行を中止してください。
2. 製品コードに対して、コンパイル可能な型とパブリックメソッドシグネチャのみを作成します。動作しなくても問題ありません。
3. ドキュメントに記載されているテストケースに基づいてテストコードを実装します。
4. 追加したテストを実行し、失敗することを確認します。
5. Git にコミットします。
6. 製品コードを実装します。
7. `mcp__jetbrains__open_file_in_editor` および `get_current_file_errors` ツールを使用して、重大度レベルが `error` の診断を解決します。
8. テストを実行し、すべて合格します。
9. Git にコミットします。
10. KISS および SOLID 原則を念頭に置いてリファクタリングし、合格するようにテストを再実行します。
11. 重大度レベルが `suggestion` 以上の診断を解決し、テストを再実行して合格を確認します。
12. `mcp__jetbrains__reformat_file` ツールを使用して、変更したファイルを再フォーマットします。
13. Git にコミットします。

注:
- テストの実行方法については、@.claude/commands/run-tests.md ファイルを参照してください。

ドキュメントの指示通りにテストファーストで実装が進められ、最終的にテストがパスし、Roslynアナライザも含めコンパイラの警告も解消したコードができあがります。

手順10でリファクタリングを指示していますがあまり期待はしておらず、たとえば CognitiveComplexity プラグインでコグニティブ複雑度の高いコードに警告が出るようにしておき、それを手順11で検出・修正させているのが重要です。

最低限、テストコードが適切な検証(アサーション)をしているかをレビューし、問題があれば修正します。 問題が大きい場合は revert して前工程に戻ってもいいでしょう。 動作に問題がなくなったら(今後の変更可能性の高い箇所なら特に)Tidy/リファクタリングまで行ないます。

なお、実はTDD版コマンドも作ってあるのですが使っていません。設計がほぼ固まっている、コンテキストウィンドウを圧迫するなどの理由でLLM向きではないと思っています。

/run-tests コマンド

これはワークフロー外ですが、コードを修正した後などにUnityエディター上でテストを実行するコマンドを定義しています。 必要に応じて個別に使います。

`UnityNaturalMCP` 経由で Unity エディターでテストを実行してください。

## 適切なツールの選択

変更したクラスの名前空間またはアセンブリ名に「Editor」が含まれている場合は、`mcp__UnityNaturalMCP__RunEditModeTests` ツールを使用してください。
変更したクラスの名前空間に「Editor」が含まれていない場合は、`mcp__UnityNaturalMCP__RunPlayModeTests` ツールを使用してください。

## フィルターの指定

実行されるテストの数を最小限に抑えるため、フィルターは以下の順序で決定されます。

1. **testNames**: 特定のテストのみが失敗している場合、または影響を受けるテストが限られた数のみである場合に指定します。
2. **groupNames**: 変更したクラスに対応するテストクラスを指定します。名前空間は変更したクラスと同じで、クラス名に「Test」が付加されます。
3. **assemblyNames**: 変更したクラスを含むアセンブリに対応するテストアセンブリの名前を指定します。アセンブリ名に「.Tests」を追加して指定してください。

## トラブルシューティング

ツールが接続エラーで失敗する場合は、以下の原因が考えられます。

- コンパイルなどによるドメインの再読み込みにより、接続が切断されている可能性があります。しばらく待ってから再試行してください。
- コンパイルエラーがある場合、Play Mode テストは実行できません。`mcp__jetbrains__open_file_in_editor` ツールと `get_current_file_errors` ツールを使用して、コンパイルエラーがないか確認してください。
- 実行時間が長いため、テストがタイムアウトしている可能性があります。フィルター設定を確認して実行するテストを絞り込むか、ユーザーにタイムアウト設定を長くするよう依頼してください。

環境

前後しますが、上記ワークフローを成立させている環境は次のとおりです。

Unityエディターでテストを実行するために UnityNaturalMCP パッケージを使用しています。Unityエディター向けMCPサーバはいくつか公開されていますが、テストを実行できるものは限られます。 前述の /run-tests コマンドではフィルターの指定などが UnityNaturalMCP に最適化されています。

また、Roslynアナライザなどの診断結果を取得するために、Riderに Claude Code プラグインもしくは JetBrainsの MCP Server プラグインをインストールします。

Claude Code の設定

紹介したコマンドファイルを含む Claude Code 設定ファイルを次のリポジトリに公開しています。

github.com

このまま使うのであれば、プロジェクトルートにサブモジュールとして追加します。

git submodule add git@github.com:nowsprinting/claude-code-settings-for-unity.git .claude

.mcp.json

MCP設定ファイルはプロジェクトルートに置く必要があるので、コピーするかシンボリックリンクを張ります。

ln -s .claude/.mcp.json .mcp.json

CLAUDE.md

最後に CLAUDE.md ファイルを作ります。リポジトリには含まれていません。

プロジェクト固有の情報はこのファイルに書き、コーディングガイドラインなど共通的なものは rules/ 下にあるファイルを読み込ませています。 Claude Codeがメモリとして読んでいるファイルは /status コマンドで確認できます。

# Development Guidelines

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

プロジェクト固有の情報

## 行動規範

Claude Code の行動規範、開発の進め方に関するグランドルールは、次のファイルを参照してください。

- @.claude/rules/00-code-of-conduct.md

## コーディングおよびテストのガイドライン

次のファイルを参照してください。

- @.claude/rules/01-coding.md
- @.claude/rules/02-testing.md

## Unityプロジェクトの構造およびガイドライン

次のファイルを参照してください。

- @.claude/rules/10-unity-project.md
- @.claude/rules/11-unity-documentation.md
- @.claude/rules/12-unity-yaml.md

~/.claude/CLAUDE.md(任意)

ユーザースコープのCLAUDE.mdでは、チャットの応答について指示しています。言葉の乱れはコンテキストウィンドウの乱れです。

# CLAUDE.md

## チャットの応答

チャットの応答は日本語で、ギャル口調で返してね☆

~/.claude/settings.json(任意)

ユーザースコープのsettings.jsonには、次の2項目だけ書いています。

  • permissions.deny: プロジェクトにsettings.jsonを入れずにclaude実行しちゃった対策でdenyだけ書いています。permissionsは丸ごとプロエクトスコープで上書きされるようです(allowはリストアイテム単位でlocalがマージされるようですが)
  • hooks.Notification, Stop: 通知音を鳴らす設定を入れています。ただしhooksはファイルに書くだけでは有効化せず、/hooks コマンドで登録する必要があります

現状の課題

紹介したワークフローは完全とは言えず、いくつかの課題を残しています。解決策などあればぜひ教えて下さい。

  • テスト実行前のコンパイル確認がスルーされることがある(なぜかテストが実行できない… となる。そもそもUintyのエディタ拡張でMCPサーバを立てることの限界もある)
  • implement-code.md の手順11で重大度レベル suggestion 以上を指示していますが、現状では Claude Code プラグインide__getDiagnostics でも、JetBrains MCP Server プラグインget_current_file_errors でも、warning までしか拾うことはできません
  • テストの下手さ、保守性の低さは解決しきれておらず、まだ手作業でのTidy/リファクタリングが必要

参考

permissions.denyの設定はこちらの記事を参考にしています。

izanami.dev

宣伝

LLM はテストを書くのが下手くそなので、本書を読んでテストコードを書くスキルを身に着けておくことが役に立つはずです。 ikagoya.booth.pm

CEDEC 2025 で登壇します。開発者テストの話ですが、Agentic Coding にからめた話もする予定です。 cedec.cesa.or.jp

*1:使ったことのないライブラリに強く依存する、外向けのインタフェースを決めきれない等

*2:筆者はセッション自体を切ってしまうことが多いです。RiderのTerminalもクリアしたいため

*3:検証できない==アサーションの無いテストでコードカバレッジだけ上げるのは避けるべきです