AIにテスト用データを作らせるときは、見た目の自然さだけでなく、表同士のつながりを確認します。注文の顧客IDが顧客表にない、注文IDが重なる、数量や状態が仕様に合わないと、試したい機能より先にデータの不整合で止まる場合があります。
この記事では、架空の顧客3件・注文6件から、二つのCSVと検算表を作ります。入力を拒否する試験用の不正例は、正常データと別に管理します。実顧客を加工したデータや、AIサービスの生成結果ではありません。手製の例をローカルで検査したものです。
目次
件数だけでなく、列と関係を先に指定する
今回は顧客一行が一顧客、注文一行が一注文です。顧客IDと注文IDはそれぞれの表で重複せず、空欄も許しません。各注文のcustomer_idは、顧客表のcustomer_idに存在する必要があります。
このような表間の関係は、データベースでは外部キーなどの制約で表します。PostgreSQLの公式説明も、参照する値が相手の表に存在することで参照整合性を保つと説明しています。今回は同じ考え方をCSVの検査に使い、DB操作は行いません。PostgreSQL公式:制約(新しいタブで開く)
表は横にスクロールできます
| 項目 | この架空例の条件 |
|---|---|
| 顧客表 | customer_id、label。3行 |
| 注文表 | order_id、customer_id、quantity、status。6行 |
| ID | 文字列として保持。一意で空欄なし |
| 参照 | 注文の顧客IDは顧客表に存在する |
| 数量 | 正の整数 |
| 状態 | NEW、CONFIRMED、CANCELLEDのいずれか |
| 今回の配分 | 顧客ごとに注文2件。CONFIRMED 3件・NEW 2件・CANCELLED 1件 |
最後の配分も、説明用に決めた条件です。実際の顧客分布や注文状況を再現したものではありません。何を試したいかによっては、注文がない顧客、注文が集中する顧客、最大数量などの別のデータが必要です。
正常データを二つのCSVへ分ける
顧客表の例です。labelも架空の表示名で、実在する人や組織を示しません。
customer_id,label
C001,架空顧客A
C002,架空顧客B
C003,架空顧客C
注文表は次の6行です。数量は1〜3の範囲を使っていますが、仕様上の上限を3と決める例ではありません。
order_id,customer_id,quantity,status
O001,C001,1,CONFIRMED
O002,C001,2,CANCELLED
O003,C002,1,CONFIRMED
O004,C002,3,NEW
O005,C003,2,CONFIRMED
O006,C003,1,NEW
同じ顧客IDが注文表に何度も出ることは正常です。一意にする対象は注文IDで、注文表のcustomer_idまで重複禁止にしません。逆に顧客表のcustomer_idが二行あれば、どちらを参照するかが曖昧になるため、今回の条件では不正です。
CSVは手でカンマ連結せず、採用言語のCSVライターなどで保存します。Pythonのcsvモジュールは辞書形式での読み書きも扱えますが、CSVとして読めることと、IDや参照関係が正しいことは別の検査です。Python公式:csv(新しいタブで開く)
行数・参照・配分を一緒に照合する
この例では、次の結果を期待値として先に残します。生成したデータから計算した数字だけを正解にせず、依頼した条件と比較します。
表は横にスクロールできます
| 検査 | 期待値 |
|---|---|
| 顧客の行数と異なるID数 | 3行、3種類 |
| 注文の行数と異なるID数 | 6行、6種類 |
| 参照先がない注文 | 0件 |
| 顧客別の注文数 | C001、C002、C003が各2件 |
| CONFIRMED | 3件 |
| NEW | 2件 |
| CANCELLED | 1件 |
| 数量の合計 | 10 |
数量の合計10は、キャンセルを含むこの6行の入力値を足した検算値です。出荷数や実売上などの業務指標を確定したものではありません。業務の集計に使うなら、状態ごとの扱いを別に定義します。
件数が合っていても、参照先の不一致が隠れることがあります。例えばO006のC003をC999に変えても注文は6行のままです。件数だけでなく、参照先の集合と不一致の注文IDを確認します。
不正例は、一つの変更と期待する検出を記録する
正常データへ不正値を混ぜて配布すると、受け取る人が「取り込めないデータを誤って渡された」と判断するかもしれません。正常セットと、拒否やエラー表示を確認するセットを分けます。
表は横にスクロールできます
| 不正例ID | 正常セットから変える箇所 | 検出したいこと |
|---|---|---|
| N01 | O006の顧客IDをC999へ変更 | 参照先がない注文O006を検出 |
| N02 | O006の注文IDをO001へ変更 | 注文ID O001の重複を検出 |
| N03 | O004の数量を0へ変更 | 正の整数という条件への違反 |
| N04 | O004の状態をDONEへ変更 | 許可した状態にない値を検出 |
この4例は別々のデータセットです。変更を積み重ねた一つの不正ファイルではありません。検出する理由とIDを残し、同じ検査にかけたとき、正常セットは通り、各不正例は狙った違反として見つかるかを確認します。
ただし、検査スクリプトで違反を見つけられたことと、実アプリが適切に拒否・表示することは別です。アプリの保存処理やエラー表示を試す場合は、それに対応する期待動作と実行結果を追加します。
AIへの依頼には、正常と不正の区別を入れる
次の仕様に合う架空のテストデータ案を作ってください。
実在の顧客情報や本番データは使いません。
顧客表3行:customer_id、label。
注文表6行:order_id、customer_id、quantity、status。
顧客IDと注文IDは各表で一意、空欄なし。
注文の顧客IDは顧客表に存在させてください。
quantityは正の整数。statusはNEW、CONFIRMED、CANCELLED。
各顧客へ注文2件。状態数はCONFIRMED3、NEW2、CANCELLED1件。
正常CSV2個と、仕様との照合結果を別に出してください。
不正例は正常CSVへ混ぜず、1箇所だけ変えた別セットにしてください。
各不正例に、変更箇所と期待する検出理由・対象IDを付けてください。
未指定の上限、業務上の意味、個人情報を追加しないでください。
実際に検査していなければ、検証済みと書かないでください。
件数を増やす場合は、先に小さいセットで列名、ID、参照、状態の規則を確かめます。乱数を使う生成コードなら、再現に必要な設定や生成器の版も記録します。同じ条件を指定した会話だけで、毎回まったく同じデータになるとは扱いません。
検算をAIだけへ任せず、CSVを読み直して、必須列、空欄、一意性、参照、数量、状態を調べます。今回の正常・不正セットはローカルでこの対応を確認しましたが、あらゆる不正入力を検出する汎用検査を保証するものではありません。
検査用データの範囲を、実データの代表性へ広げない
今回の正常セットはすべての顧客に注文が2件あり、数量も小さな整数です。空の表、注文のない顧客、大きな件数、桁あふれ、文字コードの問題、取り込み途中の失敗は含みません。必要なケースは対象機能の要件から追加します。
架空データを作ったことだけで、実環境の分布、性能、業務上の例外を再現したとは言えません。生成したラベルも正式名称ではありません。テスト用であること、用途、列の定義、期待値、正常・不正の区分を、ファイルと一緒に残します。
成果物は、二つのCSV、仕様と期待件数、不正例ごとの変更記録、検査結果です。ケースの期待動作を設計する工程と、そこへ渡すデータを作る工程を分けると、失敗が機能の問題か、データ自体の問題かを調べやすくなります。
参考資料
公式資料の確認日:2026年10月20日。顧客3件・注文6件と不正例は手製の架空データです。CSVの読み込みと条件照合をローカルで行いました。AI生成、DBへの投入、実アプリの拒否動作、実データの代表性、負荷、画面表示は検証していません。
