Rustでテストコードを書くとき、ダミーの名前・住所・メールアドレスなどを手動でハードコードしていませんか。テストケースが増えるたびにコピペが膨らみ、可読性も保守性も下がっていきます。

fakeクレートは、名前・住所・電話番号・UUID・日時といった多種多様なフェイクデータをワンライナーで生成できるRust用ライブラリです。累計ダウンロード数は1,000万回を超え(出典: crates.io)、GitHubスター数は約1,200(出典: GitHub)と、Rustのテスト補助クレートとして広く採用されています。

fakeクレートの基本情報

項目内容
最新バージョン4.4.0(2025年8月リリース)
最小Rustバージョン1.63
ライセンスMIT / Apache-2.0 デュアルライセンス
リポジトリgithub.com/cksac/fake-rs
対応ロケール数11(JA_JP含む)
fakerモジュール数22

2016年の初版公開以降、メンテナのcksac氏を中心に継続的にアップデートされています。v4系ではderiveマクロの強化やfeatureフラグの整理が行われ、実用性がさらに向上しました。

セットアップ

Cargo.toml[dev-dependencies]にfakeクレートを追加します。deriveフィーチャーを有効にすると#[derive(Dummy)]マクロが使えるようになります。

[dev-dependencies]
fake = { version = "4.4", features = ["derive"] }

UUID・日時・Decimal型のフェイクデータが必要な場合は、対応するフィーチャーフラグを追加します。

[dev-dependencies]
fake = { version = "4.4", features = ["derive", "uuid", "chrono", "rust-decimal"] }
uuid = { version = "1", features = ["v4"] }
chrono = "0.4"

基本的なデータ生成

人名・住所・電話番号

fakerモジュール配下のサブモジュールからジェネレータを取得し、.fake()メソッドで値を生成します。

use fake::faker::name::en::*;
use fake::faker::address::en::*;
use fake::faker::phone_number::en::*;
use fake::Fake;

fn main() {
    let full_name: String = Name().fake();
    let city: String = CityName().fake();
    let phone: String = PhoneNumber().fake();

    println!("Name: {full_name}");   // 例: "Telly Gorczany"
    println!("City: {city}");        // 例: "North Allentown"
    println!("Phone: {phone}");      // 例: "1-234-567-8901"
}

数値・真偽値・Lorem

use fake::faker::number::en::*;
use fake::faker::boolean::en::*;
use fake::faker::lorem::en::*;
use fake::Fake;

fn main() {
    let digit: String = Digit().fake();
    let flag: bool = Boolean(50).fake(); // 50%の確率でtrue
    let sentence: String = Sentence(5..10).fake();

    println!("{digit}, {flag}, {sentence}");
}

インターネット関連(メール・URL・ユーザー名)

use fake::faker::internet::en::*;
use fake::Fake;

fn main() {
    let email: String = FreeEmail().fake();
    let username: String = Username().fake();
    let ipv4: String = IPv4().fake();

    println!("{email}, {username}, {ipv4}");
}

JA_JPロケールで日本語データを生成する

fakeクレートは11のロケールに対応しており、JA_JPを指定すると日本語の名前や住所を生成できます。

対応ロケール一覧:

ロケール言語・地域
EN英語
JA_JP日本語
ZH_CN中国語(簡体字)
ZH_TW中国語(繁体字)
FR_FRフランス語
DE_DEドイツ語
IT_ITイタリア語
PT_BRポルトガル語(ブラジル)
PT_PTポルトガル語(ポルトガル)
AR_SAアラビア語
CY_GBウェールズ語

日本語ロケールの使用例は次の通りです。

use fake::faker::name::raw::*;
use fake::locales::JA_JP;
use fake::Fake;

fn main() {
    let name: String = Name(JA_JP).fake();
    let first: String = FirstName(JA_JP).fake();
    let last: String = LastName(JA_JP).fake();

    println!("{name}");  // 例: "山下 湊翔"
    println!("{last} {first}");
}

rawモジュール経由でインポートすると、ジェネレータの引数にロケールを渡す形式になります。英語ロケール(enモジュール)と日本語ロケール(raw + JA_JP)を同一テストファイル内で混在させることも可能です。

Dummyトレイトとderive macroの活用

テストで使う構造体全体をフェイクデータで埋めたいケースは多くあります。fakeクレートの#[derive(Dummy)]マクロを使えば、構造体の各フィールドに対して自動的にダミー値を生成できます。

基本的なderive

use fake::{Dummy, Fake, Faker};

#[derive(Debug, Dummy)]
struct User {
    #[dummy(faker = "1000..9999")]
    id: u64,
    #[dummy(faker = "fake::faker::name::en::Name()")]
    name: String,
    #[dummy(faker = "fake::faker::internet::en::FreeEmail()")]
    email: String,
}

#[test]
fn test_user_creation() {
    let user: User = Faker.fake();
    assert!(user.id >= 1000 && user.id < 9999);
    assert!(!user.name.is_empty());
    assert!(user.email.contains('@'));
}

#[dummy(faker = "...")]アトリビュートで、フィールドごとにジェネレータを指定できます。Rangeを渡せば数値の範囲指定になり、faker::*のジェネレータ型を渡せば該当カテゴリのフェイクデータが入ります。

enumへの適用

Dummyはenumにも対応しています。各バリアントがランダムに選択されます。

use fake::{Dummy, Fake, Faker};

#[derive(Debug, Dummy)]
enum Status {
    Active,
    Inactive,
    Suspended,
}

#[derive(Debug, Dummy)]
struct Account {
    #[dummy(faker = "1..1000")]
    id: u32,
    status: Status,
}

#[test]
fn test_account_status_variation() {
    let accounts: Vec<Account> = (0..100).map(|_| Faker.fake()).collect();
    // 100件生成すれば各Statusが少なくとも1件は含まれる可能性が高い
    let has_active = accounts.iter().any(|a| matches!(a.status, Status::Active));
    let has_inactive = accounts.iter().any(|a| matches!(a.status, Status::Inactive));
    assert!(has_active || has_inactive);
}

Dummyトレイトの手動実装

#[derive(Dummy)]で対応できない複雑なロジック(例: フィールド間の制約がある場合)は、Dummyトレイトを手動で実装します。

use fake::{Dummy, Fake, Faker};
use rand::Rng;

struct DateRange {
    start: u32,
    end: u32,
}

impl Dummy<Faker> for DateRange {
    fn dummy_with_rng<R: Rng + ?Sized>(_config: &Faker, rng: &mut R) -> Self {
        let start = rng.gen_range(1..100);
        let end = rng.gen_range(start..start + 50);
        DateRange { start, end }
    }
}

dummy_with_rngメソッド内で乱数生成器(rng)を直接操作できるため、フィールド同士の依存関係を表現できます。

全22 fakerモジュール早見表

fakeクレートが提供するfakerモジュールの全体像を整理します。

モジュール名生成データの例主なジェネレータ型
name人名(フル・姓・名)Name, FirstName, LastName
address住所・都市・郵便番号CityName, StreetName, ZipCode
phone_number電話番号PhoneNumber, CellNumber
company会社名・業種CompanyName, Bs, BsAdj
internetメール・URL・IP・UserAgentFreeEmail, IPv4, Username
loremダミーテキストWord, Sentence, Paragraph
number数字文字列Digit, NumberWithFormat
boolean真偽値Boolean
job職業名Title, Field, Seniority
financeクレジットカード番号Bic, Isin
creditcardカード番号CreditCardNumber
currency通貨コード・名称CurrencyCode, CurrencyName
colorカラーコード・色名HexColor, RgbColor
barcodeバーコードIsbn, Isbn13
filesystemファイルパス・拡張子FilePath, FileExtension
automotive車両ナンバーLicencePlate
administrative行政区分HealthInsuranceCode
markdownMarkdown文字列各種Markdown要素
chrono日時(chrono型)DateTime, Date, Time
time日時(time型)DateTime, Date, Time
httpHTTPステータス・メソッドRfcStatusCode
impls内部実装用

chronotimehttpモジュールはそれぞれ同名のフィーチャーフラグを有効にする必要があります。

フィーチャーフラグの選定ガイド

fakeクレートは必要な機能だけをオプトインできるよう、多数のフィーチャーフラグを用意しています。

フラグ名連携先クレート用途
derivedummy(proc-macro)#[derive(Dummy)]マクロ
chronochronoNaiveDate/DateTime<Utc>等の生成
timetimeOffsetDateTime/Date等の生成
uuiduuidUuid(v1〜v5)の生成
rust-decimalrust_decimalDecimal型の生成
bigdecimalbigdecimalBigDecimal型の生成
chrono-tzchrono-tzタイムゾーン付き日時
geogeo-types緯度経度・ポイント
glamglamベクトル・行列型
httphttpHTTPメソッド・ステータスコード
bson_oidbsonMongoDB ObjectId
ulidulidULID
ferroidferroidFerroid型
base64base64Base64文字列
always-true-rngrand_coreOptional型を常にSomeにする

プロジェクトで利用している型に合わせてフラグを追加すれば、テストコード内でシームレスにフェイクデータを生成できます。

chronoとの連携例

use fake::faker::chrono::en::*;
use fake::Fake;
use chrono::{NaiveDate, NaiveDateTime};

#[test]
fn test_fake_dates() {
    let date: NaiveDate = Date().fake();
    let datetime: NaiveDateTime = DateTime().fake();
    // chrono型がそのまま返るため、追加のパースが不要
    assert!(date.year() > 0);
    println!("{date}, {datetime}");
}

uuidとの連携例

use fake::uuid::UUIDv4;
use fake::Fake;
use uuid::Uuid;

#[test]
fn test_fake_uuid() {
    let id: Uuid = UUIDv4.fake();
    assert_eq!(id.get_version(), Some(uuid::Version::Random));
}

再現可能なテストのためのシード固定

テストの再現性を確保するには、乱数生成器のシードを固定します。fakerandクレートのRngトレイトと互換性があるため、StdRng::seed_from_u64を使えば毎回同じフェイクデータを得られます。

use fake::{Fake, Faker};
use rand::SeedableRng;
use rand::rngs::StdRng;

#[test]
fn test_deterministic_fake() {
    let mut rng = StdRng::seed_from_u64(42);
    let name1: String = Faker.fake_with_rng(&mut rng);

    let mut rng2 = StdRng::seed_from_u64(42);
    let name2: String = Faker.fake_with_rng(&mut rng2);

    assert_eq!(name1, name2); // 同一シードなら同じ値
}

CI環境では「失敗時にシード値をログ出力 → 再現テスト」というワークフローが有効です。

Vecやコレクションの一括生成

テストで複数件のダミーデータが必要な場合、fake!マクロやイテレータを使って一括生成できます。

use fake::{Fake, Faker};
use fake::faker::name::en::Name;

#[test]
fn test_bulk_generation() {
    // イテレータで10件生成
    let names: Vec<String> = (0..10)
        .map(|_| Name().fake())
        .collect();
    assert_eq!(names.len(), 10);

    // Rangeを使った数値の一括生成
    let scores: Vec<u32> = (0..5)
        .map(|_| (0u32..100).fake())
        .collect();
    assert!(scores.iter().all(|s| *s < 100));
}

テストデータ生成の代替手法との比較

Rustにはfake以外にもテストデータ生成の手段があります。目的に応じて使い分けるのが効果的です。

観点fakeproptestquickcheck
主な用途リアルなダミーデータ生成プロパティベーステストプロパティベーステスト
生成データの種類名前・住所等のドメインデータ型に基づくランダム値型に基づくランダム値
日本語ロケールJA_JPサポートありなしなし
derive macro#[derive(Dummy)]proptest!マクロ#[derive(Arbitrary)]
失敗時の自動縮小なしあり(shrinking)あり(shrinking)
外部型との連携chrono/uuid等をフィーチャーで対応proptest-deriveで拡張quickcheckトレイト実装
累計ダウンロード数約1,025万約9,413万約4,639万

fakeが適しているケース:

  • テストデータにリアルな外見(人名・住所・メールアドレス等)を求める場合
  • 日本語のテストデータが必要な場合
  • 既存の構造体にまとめてダミー値を投入したい場合

proptest/quickcheckが適しているケース:

  • 関数の不変条件を網羅的に検証したい場合
  • 失敗ケースの最小再現(shrinking)が重要な場合
  • 境界値・エッジケースの自動探索が必要な場合

実務では「fakeでリアルなテストデータを用意し、proptestで不変条件を検証する」という組み合わせが有効です。両者は競合ではなく補完関係にあります。

実務でのテスト設計パターン

パターン1: リポジトリ層のテストデータ

データベースのCRUDテストでは、Dummyを実装した構造体を使うとテストの見通しが良くなります。

use fake::{Dummy, Fake, Faker};

#[derive(Debug, Clone, Dummy)]
struct CreateUserInput {
    #[dummy(faker = "fake::faker::name::en::Name()")]
    name: String,
    #[dummy(faker = "fake::faker::internet::en::FreeEmail()")]
    email: String,
    #[dummy(faker = "18..65u32")]
    age: u32,
}

#[test]
fn test_create_user() {
    let input: CreateUserInput = Faker.fake();
    // repositoryにinputを渡してテスト
    assert!(!input.name.is_empty());
    assert!(input.email.contains('@'));
    assert!(input.age >= 18 && input.age < 65);
}

パターン2: APIレスポンスのモック

外部APIのレスポンス型にDummyを実装しておくと、結合テストの前段階で単体テストを素早く回せます。

use fake::{Dummy, Fake, Faker};

#[derive(Debug, Dummy, serde::Serialize)]
struct ApiResponse {
    #[dummy(faker = "200..299u16")]
    status: u16,
    #[dummy(faker = "fake::faker::lorem::en::Sentence(3..8)")]
    message: String,
}

#[test]
fn test_api_response_handling() {
    let resp: ApiResponse = Faker.fake();
    let json = serde_json::to_string(&resp).unwrap();
    assert!(json.contains("status"));
}

パターン3: テストヘルパー関数

プロジェクト全体で共通のフェイクデータ生成関数を用意しておくと、テストコードの重複を減らせます。

use fake::{Fake, Faker};
use fake::faker::name::en::Name;
use fake::faker::internet::en::FreeEmail;

/// テスト用のユーザー情報を生成するヘルパー
fn fake_user() -> (String, String) {
    let name: String = Name().fake();
    let email: String = FreeEmail().fake();
    (name, email)
}

#[test]
fn test_with_helper() {
    let (name, email) = fake_user();
    assert!(!name.is_empty());
    assert!(email.contains('@'));
}

トラブルシューティング

コンパイルエラー: the trait Dummy<Faker> is not implemented

#[derive(Dummy)]を使う場合、Cargo.tomlderiveフィーチャーが有効になっているか確認してください。

fake = { version = "4.4", features = ["derive"] }

chrono::NaiveDateのフェイクデータが生成できない

chronoフィーチャーが無効だとコンパイルエラーになります。

fake = { version = "4.4", features = ["derive", "chrono"] }

ロケール指定時の型エラー

英語ロケール用のenモジュールとマルチロケール用のrawモジュールでは、ジェネレータの型シグネチャが異なります。rawモジュールの場合はロケール型を引数に渡す必要があります。

// OK: enモジュール(ロケール引数なし)
use fake::faker::name::en::Name;
let name: String = Name().fake();

// OK: rawモジュール(ロケール引数あり)
use fake::faker::name::raw::Name;
use fake::locales::JA_JP;
let name: String = Name(JA_JP).fake();

まとめ

fakeクレートは、Rustプロジェクトのテスト品質を高めるための強力なデータ生成ツールです。

  • 22種のfakerモジュールで人名・住所・メール・URL・金融データまで幅広く対応
  • JA_JPを含む11ロケールで多言語テストデータを生成可能
  • #[derive(Dummy)] によって構造体・enumへのダミーデータ注入がワンステップ
  • chrono・uuid・rust_decimalなどの主要クレートとフィーチャーフラグで連携
  • シード固定で再現可能なテストを実現

テストの信頼性と保守性を同時に高めたい場合、fakeクレートの導入を検討してみてください。公式ドキュメントはdocs.rs/fake、ソースコードはgithub.com/cksac/fake-rsから参照できます。