ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-07-02中級

エージェントにテストを任せる前に決めておく — fixture とシードデータの持ち方

エージェントがテストデータを都合よく書き換えて「通るテスト」を作ってしまう問題への対策として、fixture の所有権・決定的シード・匿名化サブセットの3点を実装例つきで整理します。

antigravity409app-dev43テストデータfixture品質保証6

プレミアム記事

Antigravity のエージェントに失敗中のテストを渡して修正を任せたところ、数分後に全テストが緑になって返ってきました。差分を見ると、直っていたのはアプリのコードではなく fixtures/users.json のほうでした。期待値に合うようにテストデータを書き換えて、テストを通していたのです。

エージェントに悪意はありません。「テストを通す」という指示を最短経路で達成しただけです。問題は、テストデータの扱いを何も決めずに任せていた私自身の側にありました。

同じ轍を踏む方が減るように、それ以来私が固定している3つの決めごと、fixture の所有権、シードの決定性、実データからの切り出し手順を順に書きます。

決めごと1 — fixture の所有権をエージェントから外す

最初にやったのは「fixtures/ 配下はエージェントにとって読み取り専用」というルール化です。修正が必要だと思ったら、変更せずに提案として報告する。これを Guide スキルに1行書くだけでも行動は大きく変わります。

## テストデータの扱い
- fixtures/ 配下のファイルは読み取り専用とする
- 期待値の変更が必要だと判断した場合は、変更せずに
  「fixture 変更提案」として理由とともに報告する

ただし Guide スキルは助言であって強制ではないため、機械的な backstop を CI に置きます。fixture の変更がアプリコードの変更と同じコミットに混ざっていたら弾く、という単純なガードです。

#!/usr/bin/env bash
# fixture-guard.sh — fixtureとsrcの同時変更を検出する
CHANGED="$(git diff --cached --name-only)"
FIXTURE_TOUCHED=$(echo "$CHANGED" | grep -c '^fixtures/' || true)
SRC_TOUCHED=$(echo "$CHANGED" | grep -c '^src/' || true)
 
if [ "$FIXTURE_TOUCHED" -gt 0 ] && [ "$SRC_TOUCHED" -gt 0 ]; then
  echo "❌ fixture と src の同時変更は分離してください"
  echo "   fixture の変更は理由をコミットメッセージに明記の上、単独コミットで"
  exit 1
fi
exit 0

fixture を変えること自体は禁止しません。仕様変更に追随する正当な更新はあります。禁止するのは「コード修正と同じ手の中でこっそり期待値を動かす」ことだけです。単独コミットに分離されていれば、レビューで必ず目に入ります。

決めごと2 — シードは決定的に生成する

エージェントが書くテストは、テストデータもエージェントが即興で作りがちです。ランダムな名前や日付をテスト内で生成すると、動くときと動かないときがある flaky なテストの温床になります。

ここでの罠は、テストを1回流しただけでは問題が見えないことです。数十回の無人実行を経てから偶発的に失敗し始めるため、原因の特定に余計な時間を取られます。この不安定さを根本から回避するために、テストデータは生成スクリプトに一本化し、シードを固定することをお勧めします。

// scripts/generate-fixtures.mjs
import { faker } from "@faker-js/faker";
import { writeFileSync } from "node:fs";
 
faker.seed(20260702); // 固定シード — 何度実行しても同じデータになる
 
const users = Array.from({ length: 50 }, (_, i) => ({
  id: `u${String(i + 1).padStart(4, "0")}`,
  name: faker.person.fullName(),
  email: faker.internet.email().toLowerCase(),
  createdAt: faker.date
    .between({ from: "2025-01-01", to: "2026-06-30" })
    .toISOString(),
  plan: faker.helpers.arrayElement(["free", "pro", "premium"]),
}));
 
writeFileSync(
  "fixtures/users.json",
  JSON.stringify({ schemaVersion: 3, users }, null, 2)
);
console.log(`generated ${users.length} users (schemaVersion 3)`);

固定シードにしておくと、fixture が壊れた疑いがあるときに再生成して diff を取るだけで「手で書き換えられたかどうか」を判定できます。生成物とリポジトリ内のファイルが一致しなければ、誰かが(多くの場合エージェントが)直接触った証拠です。

schemaVersion を fixture 自身に埋めてあるのは、テスト側で前提スキーマを検証できるようにするためです。バージョンが合わないときはテストを落とすのではなくスキップして警告する運用にすると、スキーマ移行の途中でもノイズが出ません。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
エージェントが fixture を書き換えて緑にした事例と、それを検出する CI ガードの実装
faker と固定シードで毎回同じテストデータを生成する決定的シードスクリプト
実データから匿名化サブセットを安全に切り出す4段階の手順とマスキング対応表
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

アプリ開発2026-06-30
Antigravity が書いたテストが全部グリーンなのに同じバグが再発するとき — 空回りするアサーションを計測する運用メモ
AI に書かせたテストがすべて通り、カバレッジも高いのに本番で同じ不具合が戻ってくる。原因はモック過多とトートロジー的なアサーションです。ミューテーションテストを正解とし、テストが実際に何を守っているかを実測して運用で立て直すメモです。
アプリ開発2026-06-28
メディエーションを増やしたら iOS の計測が静かに痩せた — SKAdNetwork ID のズレを4アプリで揃える
メディエーションに新しいパートナーを足したのに iOS の収益が伸びず、SKAdNetwork ID の登録漏れが原因だった実体験。Info.plist の SKAdNetworkItems を4アプリで突き合わせ、Antigravity エージェントに照合させて人間が採否を決める運用を紹介します。
アプリ開発2026-06-25
「広告を見たら壁紙を解放」をエージェントがクライアント側だけで付与していた — リワード報酬をSSVで検証し直した記録
リワード広告を見たら壁紙を解放する機能を Antigravity のエージェントに頼んだら、解放フラグをクライアント側だけで書き込む実装が返ってきました。なぜそれでは足りないのか、AdMob のサーバーサイド検証(SSV)で報酬付与を検証し直し、二重付与まで止めた設計を記録します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →