FlowingDev

うまくいくまで、うまくいってるフリをしろ:開発者のためのモックデータガイド

本番の機密情報を使わずに、テストやプロトタイピング、開発で使えるリアルで構造化された偽データ。モックデータジェネレーターがどうやってそれを作り出すのか、学んでいきましょう。

ツールを試す: モックデータジェネレーター

一言で言うと

モックデータジェネレーターは、ソフトウェア開発やテストの際に、実際のユーザーデータの代わりとなる、リアルに見えるけれども偽物の情報(=データセット)を、プログラムで大量に作成するツールです。

これが解決する問題

はじめに「test」があった。そして「test2」と「asdf」も。開発者が自分のコードが動くか確認するためにフォームを埋めたり、データベースにデータを入力したりする必要があるとき、彼らはキーボードをめちゃくちゃに叩いて結果を得ていました。ユーザー1人なら、それでいいでしょう。ユーザー10人のリストなら?面倒だけど、まあ、やれなくはない。最終的にはデータベースが「ユーザー1」、「ユーザー2」、そして独創的な「ユーザー10」でいっぱいになります。

しかし、このやり方はすぐに破綻します。UIが Maximilian Æon Flux みたいな名前を扱わなきゃいけなくなったらどうしますか?手打ちした「テストユーザー」では、そんな事態に備えられません。データベースのクエリが、パフォーマンスが出るか確認するために、10件じゃなく5万件のレコードでテストする必要が出てきたら?手作業で5万人の偽ユーザーを作る時間も気力も、誰にもありません。

古くて危険な解決策は、稼働中の本番データベースのコピーをそのまま持ってくることでした。これはセキュリティとプライバシーの観点から言えば、大炎上案件です。実際の顧客の名前、メールアドレス、個人情報を、セキュリティが甘い開発者のラップトップに晒すことは、データ漏洩の時限爆弾です。ひとたび起これば、会社を沈没させかねない法的制裁(こんにちは、GDPRとHIPAA)が待っています。

モックデータジェネレーターは、これら全ての問題を解決します。一度データの「形」を定義すれば、あとはリアルに見えて、触った感じもそれっぽいけれど、完全に作り物のレコードを何千件も吐き出してくれます。これは、スーツを仕立てるテーラーが、道端の適当な人を借りてくるのではなく、汎用的なマネキンを使う違いに似ています。マネキンは予測可能で、安全で、テストに必要な標準サイズがすべて揃っています。

内部の仕組み

まるで魔法のように見えるかもしれませんが、モックデータジェネレーターは、テンプレートと、大規模な辞書、そして制御されたランダム性を賢く組み合わせたものに過ぎません。

### テンプレートとプレースホルダー

ジェネレーターの核となるのは、あなたが提供するテンプレートです。これは多くの場合、単一レコードの設計図として機能するJSONオブジェクトです。実際の値の代わりに、どんな「種類」のデータが欲しいかをジェネレーターに伝える特別なプレースホルダーを使います。

ユーザーオブジェクトを生成する必要があると想像してください。あなたのテンプレートはこんな感じになるでしょう:

{
  "userId": "{{datatype.uuid}}",
  "name": "{{person.fullName}}",
  "email": "{{internet.email}}",
  "signupDate": "{{date.past}}",
  "address": {
    "street": "{{location.streetAddress}}",
    "city": "{{location.city}}",
    "zipCode": "{{location.zipCode}}"
  }
}

それぞれの {{...}} がプレースホルダーです。名前が「John Smith」だと指示しているのではなく、「何かしらの名前」が欲しいと伝えているのです。あとはジェネレーターがうまいことやってくれます。この宣言的なアプローチは、特定の内容ではなく構造に集中できるため、非常に強力です。

### ライブラリの魔法

では、名前、メールアドレス、都市名はどこから来るのでしょうか? どこからともなく召喚されるわけではありません。それらは、データ偽装ライブラリ(JavaScript界で有名なのはFaker.jsですが、多くの言語に独自のバージョンがあります)の内部にある、大規模で事前にコンパイルされたリストやアルゴリズムから引っ張ってこられます。

上のテンプレートから単一のユーザーレコードを生成する簡単な流れは次のようになります:

  1. {{person.fullName}}: ライブラリは何千もの名前と苗字のリストを持っています。それぞれからランダムに1つずつ選び、組み合わせます。 random(firstNames) -> "Amelia"、 random(lastNames) -> "Jones"。結果:「Amelia Jones」。
  2. {{internet.email}}: これは他の生成されたフィールドに基づいていることが多いです。たった今作成した「Amelia Jones」を取り、それを amelia.jones に変え、リストからランダムに選んだドメイン(@example.com、@mail.netなど)を付け加えます。結果:amelia.jones@example.com。
  3. {{location.city}}: シンプルです。ライブラリは世界中の都市名が載った巨大なリストを持っています。そこから1つ選びます。結果:「Portsmouth」。
  4. {{datatype.uuid}}: これはリストを使いません。f81d4fae-7dec-11d0-a765-00a0c91e6bf6のような、Universally Unique Identifier(世界的に一意な識別子)を生成するための明確に定義されたアルゴリズムを使用します。

ジェネレーターはあなたのテンプレートをフィールドごとに処理し、偽のレコード全体が構築されるまで、各プレースホルダーに対応するライブラリ関数を呼び出します。1万件のレコードが欲しい?このプロセスを1万回繰り返すだけです。

### 決定性とシーディング

ここで、テストにとって極めて重要な詳細があります。もし、テストを実行するたびに「ランダムな」データが「全く同じ」セットである必要があったらどうでしょう? テストが「Amelia Jones」という名前のユーザーを期待しているのに、次の実行で「Bob Williams」が来たら、テストは失敗します。ここで「シーディング(seeding)」の出番です。

コンピューターは、真にランダムであることは苦手です。彼らが使うのは、擬似乱数生成器(Pseudorandom Number Generator、PRNG)と呼ばれるものです。PRNGは、ランダムに見える数列を生成するアルゴリズムですが、実際にはシード(seed) と呼ばれる初期値によって完全に決定されます。

  • seed = 123 で始めると、 5, 8, 2, 1, 10, ... というシーケンスが得られるかもしれません。
  • seed = 123 で再度実行すると、全く同じシーケンス 5, 8, 2, 1, 10, ... が得られます。
  • seed = 456 で始めると、全く異なるシーケンス 9, 4, 7, 3, 3, ... が得られます。

モックデータジェネレーターにシードを提供することで、実行するたびに、同じ「ランダムな」名前、同じ「ランダムな」苗字、そして同じ「ランダムな」都市をリストから同じ順序で選ぶことが保証されます。これにより、リアルでありながら完全に再現可能なデータセットが得られます。これは、安定して信頼性の高い自動テストを書く上での聖杯です。

実世界でのストーリー

理論は素晴らしいですが、実際にどう使われているか見てみましょう。

### ユーザーカード爆発事件

あるフロントエンド開発者、プリヤとしましょう、はソーシャルメディアアプリの新しいユーザープロフィールカードを構築するタスクを任されました。彼女は「Jane Doe」と標準的な「@gmail.com」アドレスをテストデータとして使い、CSSを丹念に作り上げました。カードはピクセルパーフェクトに見えました。名前とメールアドレスはきれいに1行に収まりました。彼女はその機能をリリースしました。

翌日、バグレポートが殺到しました。Dr. Alessandro O'Connell-Schäfer という名前のユーザーが登録したのです。彼の名前はレイアウトを破壊し、3行にわたって折り返され、プロフィール写真をカードの半分外に押し出してしまいました。アイスランドからの別のユーザーは、名前に非ASCII文字が含まれており、それが文字化けして ? と表示されました。レイアウトはめちゃくちゃでした。

教訓: きれいにハードコーディングされたテストデータは、嘘っぱちです。モックデータジェネレーターを使っていれば、さまざまな長さの名前、ハイフンやアポストロフィ、国際文字を含む名前を素早く生成し、これらのUIの弱点を実際のユーザーに届くずっと前に明らかにしていたでしょう。

### ページネーションのパフォーマンス悪夢

あるバックエンドチームが、新しいEコマースサイトを立ち上げようとしていました。開発者の一人、ベンは/products APIエンドポイントを担当していました。彼はローカルデータベースに「テストブック」、「テストシャツ」など、十数個のテスト製品を作成しました。製品を取得するコードを書き、ページネーション(1ページあたり25項目)を追加し、すべてが完璧に機能しました。APIは20ミリ秒で応答しました。

サイトがローンチしました。1週間以内に、製品カタログは3万アイテムに増えました。突然、ユーザーから製品ページの読み込みが非常に遅い、またはタイムアウトするという報告が上がりました。12個の製品では瞬時に終わっていたデータベースクエリが、今や巨大なテーブルをスキャンし、完了までに15秒以上かかるようになっていたのです。アプリは停止寸前でした。

教訓: 機能するということと、パフォーマンスが良いということは別物です。パフォーマンスをテストするには、現実的な「量」のデータが必要です。ベンが手作業で12個の製品を作成する代わりに、モックデータジェネレーターを使えば、数分で5万個の偽の製品を作成できたでしょう。これにより、開発中にすぐに遅いクエリが明らかになり、本番環境で大問題になる前に、必要なデータベースインデックスを追加するきっかけになったはずです。

### GDPRコンプライアンスの恐怖

ある小さなスタートアップが、巨大な潜在的投資家へのデモ準備に大忙しでした。彼らはデモを可能な限りリアルに見せたいと思っていました。手伝おうとしたジュニア開発者が、「素晴らしい」アイデアを思いつきました。彼は本番データベースに接続し、usersテーブル全体(約2000人の実在する顧客)をコピーし、それをステージング環境にロードしました。データが本物なので、デモは素晴らしく見えました!

一週間後、シニアエンジニアが何が起こったかを発見しました。パニックが勃発。実際の顧客の名前、メールアドレス、電話番号が、セキュリティの甘いステージングサーバー上に置かれ、開発チーム全体がアクセスできる状態になっていたのです。これはGDPRのようなデータプライバシー法に違反する典型的な例でした。もしそのデータが漏洩していたら、会社は壊滅的な罰金とユーザーの信頼の完全な喪失に直面していたでしょう。彼らは九死に一生を得ましたが、その後のクリーンアップはストレスフルで高価なものでした。

教訓: 開発、テスト、デモのために、絶対に、絶対に、絶対に実際の顧客データを使用してはいけません。リスクは天文学的です。モックデータジェネレーターは、一人の実在の人物を晒すことなく、本番データの構造を模倣する、安全で、倫理的で、合法的な代替手段を提供します。

よくある間違いと落とし穴

  • エッジケースを無視する。 「John Smith」スタイルの名前を何千も生成するのは簡単です。しかし、本当に長い名前は?アポストロフィを含む名前は?奇妙な文字を含む住所は? + 記号を含むメールアドレスは? 良いモック戦略には、ハッピーパスだけでなく、これらのエッジケースを具体的にテストするデータを生成することが含まれます。
  • リレーションシップを忘れる。 100人のユーザーリストと1000件の注文リストを生成するのは簡単です。しかし現実には、それらの注文はそれらのユーザーに「属して」います。よくある間違いは、無関係なデータを生成してしまうことです。良いモックのセットアップでは、リレーションシップを維持することができます。例えば、最初に userId のセットを生成し、次に orders を生成する際にそのセットから選ぶことで、データの整合性を保証します。
  • テスト用に非決定的なデータを作成する。 自動テストが、毎回異なるデータを生成するモックジェネレーターに対して実行されると、ランダムに失敗する「flaky(不安定)」なテストが生まれます。デバッグするのは悪夢です。テスト環境では、テストデータが100%再現可能であることを保証するために、常にジェネレーターにシードを設定しましょう。
  • 均一な分布を仮定する。 statusフィールドを生成し、["active", "pending", "suspended"]からランダムに選ぶと、それぞれがおおよそ33%ずつになります。現実世界のデータはめったにそんなにきれいではありません。実際には98%がアクティブなユーザーで、1.9%が保留中、0.1%が停止中かもしれません。多くのジェネレーターでは、重みを指定して、より正確に現実世界のデータ分布をモデル化することができます。

なぜ注目すべきか

まだ存在しないデータ、使うべきではないデータ、または手作業で作成するのが面倒すぎるデータが必要なときはいつでも、モックデータジェネレーターの出番です。

次のようなときに、このツールを思い出してください:

  • 新機能を構築中で、データベースのテーブルがまだ空のとき。
  • 自動テストを書いていて、一貫性があり、予測可能なデータ入力が必要なとき。
  • APIやデータベースクエリのパフォーマンステストで、何千、何百万ものレコードをシミュレートする必要があるとき。
  • UIをデザインしていて、長い文字列、奇妙な文字、さまざまなコンテンツでストレステストをしたいとき。
  • 製品のデモやスクリーンキャストを作成中で、個人情報を晒すことなくリアルに見えるデータが必要なとき。
  • 新しい開発者をオンボーディングする際に、本番データへのアクセス権を与えることなく、データが入ったデータベースで作業させたいとき。

これは、現代的で、安全で、効率的なソフトウェア開発のための基本的なツールです。

もっと深掘り

  • Faker.js - JavaScriptエコシステムで最も人気があり、包括的なモックデータ生成ライブラリの一つであるFaker.jsのドキュメント。生成できるデータの種類の多さを見るのに最適な場所です。
  • Wikipedia: Test Data Generation - この概念、その歴史、そして問題に対するさまざまなアプローチについての高レベルな概要。 (日本語版: テストデータ生成)
  • Wikipedia: Pseudorandom Number Generator (PRNG) - 「ランダムな」データがシーディングによってどのように再現可能になるかの理論的基礎。(日本語版: 擬似乱数)
  • GDPR.eu: What is GDPR? - EUのデータプライバシー規制に関する明確な説明。ルールを理解することは、テストに本番データを使用することがなぜそれほど危険なのかを明らかにするのに役立ちます。
  • Database Seeding (Laravel Docs) - 人気のWebフレームワークが、モックデータ生成(「シーダー」と「ファクトリー」を介して)を開発ワークフローに直接統合する方法の優れた例。これらの概念は、どの言語やフレームワークにも応用可能です。

理論はOK。さあ手を動かそう — 100%ブラウザ内で。

ツールを試す: モックデータジェネレーター