概要
今日も元気にClaude CodeとおしゃべりするZE
Claude Codeにフロントエンド開発で「テストして」と頼むと、ユニットテストだけ走らせて「パスしました!」と報告してくる。が、実際にはUIが壊れている。この問題に繰り返し遭遇してきたので、/test-wisdom スキルを作り、既存の /verify-ui や /headless-browser、/lazy-dev スキルとの連携をどうするかClaude Codeと議論した。その対話記録。
この記事で紹介しているスキルやスクリプトは claude-resources リポジトリで公開している。リポジトリは頻繁に更新されるため、記事中のリンクは特定のコミットハッシュに固定してある。最新版とは異なる場合がある。
/test-wisdomスキルを作りたい
Takazudo: 正直、これどう扱えばいいかよくわかんないんだけど、「テストして」ってAIに頼んだとき、AIがロジカルテストだけ走らせて終わるのが問題で。自分が考えてるテストって、こういうパターンがあるんだよね。
- unit testing
- logical function confirmation like layer
- DOM based component testing
- tests that depends on some DOM based testing framework
- built results confirmation testing
- about something needs build, confirm the built results by script. Let’s say we have template conversion system. if so, use vitest like util to confirm the results
- built results page e2e testing
- build -> server like pattern, and the UI is complex, we need /headless-browser to confirm the results. the wanted element exists, click opens the dialog without error like.
- AI based manually /headless-browser based testing
- All of those is hard to be tested by script, use AI power. basically capture the result, or do the operation with MCP Playwright, MCP chrome-devtools, and “think” with AI power
前者はピュアJSの機能テストだけど、後者は本当に難しい……というのは理解できる。人間の目で見ないとわかんないようなやつを、ユーザーインタラクション込みでシミュレートするやつ。
で、具体的にどういう失敗パターンがあるかというと、例えば「表示されてない」って自分が言ったとする。
- ロジカルテスト: フラグがtrueか → パス
- DOMテスト: displayがblockか → パス
- Playwright: 「レンダリングされてます!」 → でも違う要素かもしれない
- AIベースのキャプチャ: 「レンダリングされてないです、親divがhiddenです」 → ようやくバグが見つかる
つまり、このスキルはAIに「ゴールを達成するために今どうすればいいか考えろ」と促すためのもの。
Claude Code: 5段階のテストレベルを整理すると、各レベルで証明できることが異なる。
| Level | Type | Tools | Proves |
|---|---|---|---|
| 1 | Unit/Logic | vitest, jest | function returns correct value |
| 2 | DOM Component | vitest + jsdom, Testing Library | element exists, has attributes |
| 3 | Build Output | vitest reading built files | build pipeline correct |
| 4 | E2E Browser | /headless-browser, Playwright | rendered, clickable, interactive |
| 5 | Deterministic + Visual | /verify-ui + /headless-browser | CSS correct AND visually correct |
「テストして」と言われたとき、何が変わったかによって最低限必要なレベルが変わる。
| What changed | Minimum level |
|---|---|
| Pure logic | Level 1 |
| Component props/state | Level 2 |
| Build config, SSG | Level 3 |
| CSS, layout, visibility | Level 5 |
| Interactive UI | Level 4 |
| Visual bug | Level 5 |
Takazudoが挙げた「表示されてない」の失敗パターンも、スキルにそのまま共通の失敗パターンとしてドキュメント化する。加えて、必須の振る舞いとして以下を定義した。
- テスト計画を宣言してから実行する
- テストレベルをゴールに合わせる
- 不十分なら上位レベルにエスカレーションする
- テストされていない領域を報告する
/verify-ui と /headless-browser へのクロスリファレンスも入れた。
/verify-uiとの関係
Takazudo: 前に Claude CodeがCSSをうまく書いてくれないフィードバックループ って記事書いたとき、/verify-ui と /headless-browser 作ってあったじゃん。これとの関係どうなるんだろう。あと自分の記事も読んでみて。
Claude Code: 記事を読んだ。3つのスキルは明確にスタックを形成している。
- /test-wisdom = 戦略レイヤー: どのテストレベルが必要か?
- /verify-ui = 戦術レイヤー: 決定的なcomputed styleによるチェック
- /headless-browser = ツーリングレイヤー: ブラウザ自動化
ただ、3つの懸念がある。
1つ目。トリガーが広すぎる。「テストして」は何にでもマッチしてしまう。バックエンドのロジックテストでこのスキルが発動してもノイズになる。
2つ目。CSS作業のときに /verify-ui を明示的に参照すべき。test-wisdomのLevel 5で /verify-ui を使うことは書いてあるが、CSS変更時に真っ先に /verify-ui を使うという導線がもっと目立っていいのではないか。
3つ目。これはスキルとして発動させるべきか、それとも CLAUDE.md のガイダンスや /lazy-dev の一部として組み込んだ方がいいのではないか。
disable-model-invocationの話
Takazudo: ふーん、なるほど。でさ、その disable-model-invocation で手動呼び出し専用にする案だけど、それって自動発動が多すぎるとコンテキストが薄まるから避けるってこと?でも手動専用にしたらしたで、AIが毎回ロードしても結局すぐ忘れるんじゃない?手動でしか呼べないとなるとなおさら。
Claude Code: 両方の問題がある。自動トリガーにすると「テストして」のような汎用的なフレーズでUIとは無関係なプロジェクトでも発動してコンテキストを無駄に消費する。かといって手動専用にすると、スキルは会話ごとのコンテキストなので、新しい会話を始めるたびにスキルを呼ばなければルールは存在しないも同然になる。
根本的な問題が見えてきた。これはツールとして呼び出すものではない。フロントエンド作業中に常に意識すべき「考え方」。
アプローチとしては3つ考えられる。
3つ全部やろう
Takazudo: OK、3つ全部やって。
Claude Code: 了解。3つとも実装した。
1つ目。グローバルの CLAUDE.md に「Testing & Verification」セクションを追加した。3行で、常にロードされる。内容は「ユニットテストではビジュアルの正しさを証明できない」「CSS/レイアウト/表示の変更にはLevel 5が必要」「/verify-uiと/headless-browserを使うこと」という趣旨。
2つ目。test-wisdomのトリガーを狭めた。汎用的な「テストして」ではなく、「まだ壊れてる」「表示されてない」「見えない」のような、テストが不十分だったことを示すフレーズにした。
3つ目。lazy-devを更新した。フロントエンドセクションを、/verify-uiと/headless-browserを参照するテストレベルラダーに置き換えた。
こうすることで3層のアプローチが成立する。
- グローバルCLAUDE.md(常にロード、3行)
- /test-wisdomスキル(エスカレーション時にロード)
- /lazy-devクロスリファレンス(自律モード時にロード)
Takazudo: いいね、筋が通ってる。
—installオプションの話
Takazudo: あとさ、--install オプションをつけて、テストのルールをプロジェクトスコープの CLAUDE.md にコピーするってのはどう?プロジェクトの .claude/ に /verify-ui とか /headless-browser とかもインストールするか聞いてくれる的な。
Claude Code: CLAUDE.mdにルールを書き込む部分はいいアプローチだと思う。ただ「スキルをプロジェクトスコープにインストールする」のは問題がある。
- 重複と古くなる問題。グローバルスキルのコピーをプロジェクトに置くと、元を更新してもプロジェクト側は古いままになる
- ハードコードされたパスが壊れる。verify-uiは
~/.claude/skills/verify-ui/scripts/...を参照している。プロジェクトにコピーしたらこのパスが通らない - スキルはすでにグローバルに機能する。どのプロジェクトでも使える
結論として、--install はCLAUDE.mdのルールだけを書き込むべきで、スキル自体のコピーはしない方がいい。
パーソナルスコープとプロジェクトスコープ
Takazudo: ふーん、なるほど。そもそも一般的なClaude Codeの使い方として、こういう個人のツーリング的なスキルはグローバルの ~/.claude/ に置くのがいいのかなって思うんだけど。どう思う?
Claude Code: その通りだと思う。きれいに分離できる。
| Scope | What belongs | Examples |
|---|---|---|
| Global ~/.claude/skills/ | How you think | verify-ui, headless-browser, lazy-dev, test-wisdom |
| Project .claude/skills/ | How this project works | b4push, deploy configs |
| Global CLAUDE.md | Short universal rules | ”unit tests can’t prove visual correctness” |
--installパターンは、グローバルスキルが軽量なルールをプロジェクトのCLAUDE.mdに書き込むブリッジとして機能する。
判断基準はシンプルで、「自分の考え方に関するものならグローバル。このプロジェクトの動き方に関するものならプロジェクトスコープ。」
Takazudo: あー、なるほどね。そういう切り分けか。
—installはやめよう
Takazudo: OK、じゃあ --install はやめよう。test-wisdomは個人の脳みそ・哲学・技術理解のレイヤーのナレッジだもんね。
Claude Code: そう。test-wisdomは「自分がテストについてどう考えるか」をコード化したもので、プロジェクトにインストールするものではない。3層のアプローチで十分カバーされている。
- 常に意識すべきこと → CLAUDE.mdの3行
- テストが不十分だったとき → /test-wisdomスキルが発動
- 自律モードで作業するとき → /lazy-devがテストレベルラダーを参照
使い分けの確認
Takazudo: じゃ結局、AIがテスト周りで苦戦してるとき、自分がやることとしては、CSSの問題なら /verify-ui、もっと広い「テストの仕方が間違ってる」場面なら /test-wisdom を呼ぶ、であってる?
Claude Code: そう、その使い分けで合っている。実際のフローでは、/test-wisdomが発動すると結果的に /verify-ui や /headless-browser を呼び出すことが多い。/test-wisdomは「立ち止まって、今どのレベルのテストが必要か考える」ステップ。
例えば「まだ表示されてない」と言われたとき。
- /test-wisdomが発動 → 「これはLevel 5が必要だ」と判断
- → /verify-uiでcomputed styleを検証
- → /headless-browserでスクリーンショットを撮って確認
/test-wisdomは直接テストを実行するスキルではない。テスト戦略を考えるスキル。そこから適切なツール(/verify-ui、/headless-browser)に委譲する。
感想
自分はコレ系の知識やワークフローを詰めたスキルにhogehoge-wisdomと言う名前を付けている。なんとなくクラシックな海外RPG的なノリがして楽しいし、意味的にも合っているなと思うので。そしてそういうのはグローバルなところに持っておくというのもまぁあってるなーとなんか思った。そしてClaude Codeを使い出したときはそれ系のものをプロジェクトのスキルに入れていたけど、やはりそれは違っていると考えて正解なのかも知れない。
この/test-wisdomだけれど、その後使ってみたら、あ、それはTier5のテストですねみたいなことを言ってきたのでまぁまぁ意味はありそう。