package faker

  1. Overview
  2. Docs
Generate massive amounts of fake (but realistic) data for testing and development

Install

dune-project
 Dependency

Authors

Maintainers

Sources

faker-0.1.1.tbz
sha256=5b3e87f8fd6b9cd59e69f28030ede1412e2761ce36ff0d2c68b058c7342b2a92
sha512=b842a30de79e865d7177c3502dc3b32f4661b0ca91fc562f28b003b6f05c262b6bc6c1cc349343c3c06cdb92229d5f8a81b9df2fd64f3e91a0d8a4e689cc45b9

Description

An OCaml port of @faker-js/faker 10.6.0 with seed-for-seed output parity: for the same seed, every method returns the same value faker-js returns. All 26 modules and all 77 locales are ported.

Tags

faker fake data test-data mock testing

Added to opam-repository:

README

Faker (OCaml)

Generate massive amounts of fake (but realistic) data for testing and development.

An OCaml port of @faker-js/faker 10.6.0 with seed-for-seed output parity.

License: MIT OCaml >= 5.0

๐Ÿš€ Features

  • ๐Ÿง Person - Generate Names, Genders, Bios, Job titles, and more.
  • ๐Ÿ“ Location - Generate Addresses, Zip Codes, Street Names, States, and Countries!
  • โฐ Date - Past, present, future, recent, soon... whenever!
  • ๐Ÿ’ธ Finance - Create stubbed out Account Details, Transactions, and Crypto Addresses.
  • ๐Ÿ‘  Commerce - Generate Prices, Product Names, Adjectives, and Descriptions.
  • ๐Ÿ‘พ Hacker - โ€œTry to reboot the SQL bus, maybe it will bypass the virtual application!โ€
  • ๐Ÿ”ข Number and String - Of course, we can also generate random numbers and strings.
  • ๐ŸŒ Localization - All 77 faker-js locales, from af_ZA to zu_ZA.
  • ๐ŸŽฏ Seed-for-seed parity - For the same seed, every method returns the same value faker-js returns. The port uses the same MersenneTwister19937 generator and the same algorithms, and dune test checks this against fixtures generated by running faker-js itself.
  • ๐Ÿชถ Lightweight - Depends only on the OCaml stdlib and unix.

๐Ÿ“ฆ Install

opam install faker

For the development version, pin it from git:

opam pin add faker https://github.com/barteo/faker-ocaml.git

Then add it to your dune file:

(executable
 (name main)
 (libraries faker))

๐Ÿช„ Usage

type user = {
  user_id : string;
  username : string;
  email : string;
  avatar : string;
  password : string;
  birthdate : float; (* epoch milliseconds *)
  registered_at : float;
}

(* Bind each value with [let] so the RNG is consumed in the same order as faker-js
   (OCaml evaluates record fields right to left). *)
let create_random_user f =
  let user_id = Faker.String.uuid f in
  let username = Faker.Internet.username f in
  let email = Faker.Internet.email f in
  let avatar = Faker.Image.avatar f in
  let password = Faker.Internet.password f in
  let birthdate = Faker.Date.birthdate f in
  let registered_at = Faker.Date.past f in
  { user_id; username; email; avatar; password; birthdate; registered_at }

let () =
  let f = Faker.create () in
  let users = Faker.Helpers.multiple ~count:(`N 5) (fun _ -> create_random_user f) f in
  Array.iter
    (fun u -> Printf.printf "%s <%s>, born %s\n" u.username u.email (Faker.Date_util.to_iso u.birthdate))
    users

A few more, with a fixed seed:

let () =
  let f = Faker.create ~seed:42 () in
  print_endline (Faker.Person.full_name f);                      (* Nikita Crist *)
  print_endline (Faker.Location.street_address ~use_full_address:true f);
  print_endline (Faker.Internet.email f);
  print_endline (Faker.String.uuid f);
  Printf.printf "%d\n" (Faker.Number.int ~min:1 ~max:10 f);
  print_endline (Faker.Helpers.from_reg_exp "[A-Z]{3}-[0-9]{4}" f)

Conventions

The API mirrors faker-js, so the faker-js API reference documents every method. It translates like this:

faker-js

OCaml

faker.person.firstName({ sex: 'female' })

Faker.Person.first_name ~sex:Female f`

faker.number.int({ min: 1, max: 10 })

Faker.Number.int ~min:1 ~max:10 f

faker.string.alpha({ length: { min: 3, max: 5 } })

Faker.String.alpha ~length:(Range (3, 5)) f`

faker.number.bigInt({ max: 10n ** 30n })

Faker.Number.big_int ~max:(Faker.Bigint.of_string "1000000000000000000000000000000") f

faker.helpers.arrayElement(arr)

Faker.Helpers.array_element arr f

faker.helpers.enumValue(Color)

Faker.Helpers.enum_value [ ("Red", "red"); ... ] f

new Faker({ locale: [en, base], seed })

Faker.create ~seed ()

new Faker({ locale: [de_AT, de, en, base] })

Faker.create ~locale:(Faker.Locales.De_AT.chain ()) ()

fakerDE

Faker.Locales.De.faker ()

de

Faker.Locales.De.definition ()

allFakers, allLocales

Faker.All_locales.all_fakers, all_locales

new SimpleFaker({ seed })

Faker.create_simple ~seed ()

faker.seed(42)

Faker.seed f 42

faker.seed()

Faker.seed_random f

faker.setDefaultRefDate(date)

Faker.set_default_ref_date f ms, or Faker.set_default_ref_date_input f (`Str iso)

faker.setDefaultRefDate()

Faker.reset_default_ref_date f

faker.getMetadata()

Faker.get_metadata f

faker.rawDefinitions / faker.definitions.person.first_name

Faker.definitions f / Faker.definition f "person" "first_name"

mergeLocales([de, en])

Faker.merge_locales [ de; en ]

  • The faker instance always comes last, and options are optional labelled arguments in snake_case.
  • A NumberOrRange option becomes `N n or `Range (min, max). String unions become polymorphic variants.
  • Dates are float epoch milliseconds. Use Faker.Date_util.to_iso and of_iso to convert.
  • A bigint is a Faker.Bigint.t, an arbitrary-precision integer (of_int, of_string, to_string, ...).
  • Errors raise Faker.Faker_error msg, with the same messages as faker-js.

๐Ÿ’Ž Modules

All 26 faker-js modules are ported, each as Faker.<Module>: Airline, Animal, Book, Color, Commerce, Company, Database, Datatype, Date, Finance, Food, Git, Hacker, Helpers, Image, Internet, Location, Lorem, Music, Number, Person, Phone, Science, String, System, Vehicle and Word.

Templates

Faker.Helpers.fake combines faker methods using a mustache string format:

print_endline
  (Faker.Helpers.fake "Hello {{person.prefix}} {{person.lastName}}, how are you today?" f)

๐ŸŒ Localization

All 77 faker-js locales are included. Faker.create uses English (en with base as fallback). Every locale has a module in Faker.Locales, named after its code (De, De_AT, Pt_BR, Zh_CN, ...), with the same pieces faker-js exports:

let () =
  let f = Faker.Locales.De.faker () in      (* fakerDE: a shared instance *)
  Faker.seed f 42;
  print_endline (Faker.Person.full_name f); (* Melinda Dragu *)
  (* Your own instance, with the same fallback chain as fakerDE_AT: de_AT, de, en, base. *)
  let g = Faker.create ~locale:(Faker.Locales.De_AT.chain ()) ~seed:42 () in
  print_endline (Faker.Location.city g)

Like importing a single locale from @faker-js/faker, a program only links the locales it references, so English-only programs stay small. Faker.All_locales (allLocales, allFakers) references every locale and links all of them (about 1.2 MB more).

Locale data is generated from the faker-js npm package with node tools/gen_locale.mjs, so it is never hand-copied (see CONTRIBUTING.md).

โš™๏ธ Setting a randomness seed

If you want consistent results, you can set your own seed:

let () =
  let f = Faker.create () in
  Faker.seed f 123;
  let first_random = Faker.Number.int f in
  (* Setting the seed again resets the sequence. *)
  Faker.seed f 123;
  let second_random = Faker.Number.int f in
  Printf.printf "%b\n" (first_random = second_random)  (* true *)

Faker.Date methods are relative to the current time by default. For reproducible dates, also fix the reference date with Faker.set_default_ref_date f ms, or pass ~ref_date.

๐Ÿ›  Development

opam install dune alcotest
dune build
dune test                       # parity fixtures + property tests
ONLY=person dune test --force   # one module's parity fixtures
ONLY='sweep_*' dune test --force  # every method in every locale (or sweep_de, l10n_ja, ...)
dune exec ./bin/demo.exe -- 42  # one value per module
dune exec ./bin/demo.exe -- 42 ja  # ... in another locale

Fixtures come from the real faker-js package (tools/package.json pins 10.6.0):

cd tools && npm install
node gen_locale.mjs             # lib/locales/: every locale's data, chain and instance
node gen_unicode.mjs            # lib/internal/unicode_*.ml: JS case mapping and NFKD tables
node gen_fixtures.mjs [group]   # test/expected/expected_<group>.ml from tools/cases/<group>.mjs

See docs/PORTING.md for the porting conventions and the parity pitfalls, such as FMA contraction on arm64, UTF-16 vs UTF-8, and JS number formatting.

โš ๏ธ Known differences

  • Date strings are parsed as ISO 8601. A date-time string without a timezone offset is read as UTC, while JS reads it as local time.
  • finance.amount ~auto_format:true always formats as en-US. faker-js uses the runtime's default locale (not the faker locale), so this matches node running in en-US.
  • Through helpers.fake, a date-returning method yields an ISO string. JS would produce its locale-dependent Date.toString().
  • location.nearbyGPSCoordinate uses a port of V8's fdlibm sin/cos, which is bit-exact with node on arm64.
  • Distributor.exponential calls the platform's libm pow, as node's Math.pow does. Its results can differ in the last bit between platforms (e.g. FreeBSD vs Linux/macOS) in faker-js too, so they match faker-js running on the same platform.

โœจ Contributing

Please read the Contributing Guide and the Porting Guide before making a pull request.

๐Ÿ“˜ Credits

All the data and algorithms come from faker-js. Thanks to the faker-js team and everyone who contributed to it, and to Marak Squires for the original faker.js.

๐Ÿ”‘ License

MIT. It includes the faker-js license, since the locale data is derived from faker-js.

Dependencies (2)

  1. ocaml >= "5.0"
  2. dune >= "3.0"

Dev Dependencies (2)

  1. odoc with-doc
  2. alcotest with-test

Used by

None

Conflicts

None