Generates realistically-looking fake data
- About
- Comparison with other JVM-based faker libraries
- Usage
- CLI
- Data Providers
- Migrating to 1.0
- Build and Deploy
- Contributing
- Thanks
- Licence
Port of a popular ruby faker gem written completely in kotlin. Generates realistically looking fake data such as names, addresses, banking details, and many more, that can be used for testing purposes during development and testing.
While there are several other libraries out there with similar functionalities, I had several reasons for creating this one:
- most of the ones I've found are written in java and I wanted to use kotlin
- none of them has the functionality I needed
- I didn't feel like forking an existing kotlin-based lib and refactoring the entire codebase, especially with it not being maintained for the past couple of years.
So why use this one instead? I've decided to make a comparison between this lib and the others that have been out there for quite some time.
The benchmarks time is an average execution time of 10 consecutive runs. Each run includes creating a new Faker instance and generating a 1_000_000 values with the function returning a person's full name.
Note:
benchmarks for blocoio/faker
could not be done due to unexpected exceptions coming from the lib,
benchmarks for moove-it/fakeit
could not be done due to android dependencies in the lib
kotlin-faker | DiUS/java-faker | Devskiller/jfairy | blocoio/faker | moove-it/fakeit | |
---|---|---|---|---|---|
language | kotlin | java | java | java | kotlin |
number of available providers (address , name , etc.) |
150 | 73 | 8 | 21 | 36 |
number of available locales | 55 | 47 | 10 | 46 | 44 |
extra functionality | ✅ | ❎ | ❎ | ❎ | ❎ |
actively maintained | ✅ | ✅ | ✅ | ✅ | ❎ |
cli-bot app | ✅ | ❎ | ❎ | ❎ | ❎ |
benchmarks | 5482ms | 17529.9ms | 15036.5ms | NA | NA |
With gradle
Add bintray repository:
repositories {
maven {
url 'https://dl.bintray.com/serpro69/maven/'
}
}
Add dependency:
dependencies {
implementation 'io.github.serpro69:kotlin-faker:$version'
}
With maven
Add bintray repository:
<repositories>
<repository>
<id>serpro69-maven</id>
<url>https://dl.bintray.com/serpro69/maven/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
Add dependency:
<dependencies>
<!--Add dependency-->
<dependency>
<groupId>io.github.serpro69</groupId>
<artifactId>kotlin-faker</artifactId>
<version>${version}</version>
</dependency>
</dependencies>
Downloading a jar
The jar and pom files can also be found at this link
Hotfixes are automatically built and deployed to bintray on every push to master that passes tests. This means that it could be cumbersome to always have the latest hotfix version in your dependencies, therefore it is recommended to use a dependency range instead, providing only major and minor versions.
In maven:
<dependency>
<groupId>io.github.serpro69</groupId>
<artifactId>kotlin-faker</artifactId>
<version>[1.1,1.2)</version> <!--Use latest version between 1.1 (inclusive) and 1.2 (exclusive)-->
</dependency>
In gradle:
dependencies {
implementation 'io.github.serpro69:kotlin-faker:1.1.+'
}
Major and minor versions are still bumped manually and therefore are not that frequent. The project adheres to semantic versions rules.
val faker = Faker()
faker.name.firstName() // => Ana
faker.address.city() // => New York
If no FakerConfig
instance is passed to Faker
constructor then default configuration will be used:
locale
is set toen
random
is seeded with a pseudo-randomly generated number.uniqueGeneratorRetryLimit
is set to100
Faker supports seeding of it's PRNG (pseudo-random number generator) through configuration to provide deterministic output of repeated function invocations.
val fakerConfig = FakerConfig.builder().create {
random = Random(42)
}
val faker = Faker(fakerConfig)
val city1 = faker.address.city()
val name1 = faker.name.name()
val otherFaker = Faker(fakerConfig)
val city1 = otherFaker.address.city()
val name1 = otherFaker.name.name()
city1 == city2 // => true
name1 == name2 // => true
Faker supports generation of unique values. There are two ways to generate unique values:
Unique values for entire provider
val faker = Faker()
faker.unique.enable(faker::address) // enable generation of unique values for address provider
repeat(10) { faker.address.country() } // will generate unique country each time it's called
To clear the record of unique values that were already generated:
faker.unique.clear(faker::address) // clears used values for address provider
faker.unique.clearAll() // clears used values for all providers
To disable generation of unique values:
faker.unique.disable(faker::address) // disables generation of unique values for address provider and clears all used values
faker.unique.disableAll() // disables generation of unique values for all providers and clears all used values
Unique values for particular functions of a provider
val faker = Faker()
repeat(10) { faker.address.unique.country() } // will generate unique country each time `country()` is prefixed with `unique`
repeat(10) { faker.address.city() } // this will not necessarily be unique (unless `faker.unique.enable(faker::address)` was called previously)
To clear the record of unique values that were already generated:
faker.address.unique.clear("city") // clears used values for `faker.address.unique.city()` function
faker.address.unique.clearAll() // clears used values for all functions of address provider
Configuring retry limit
If the retry count of unique generator exceeds the configured value (defaults to 100
)
then RetryLimitException
will be thrown.
It is possible to re-configure the default value through FakerConfig
:
val config = FakerConfig.builder().create {
uniqueGeneratorRetryLimit = 1000
}
val faker = Faker(config)
Excluding values from generation It is possible to exclude values from being generated with unique generator:
val faker = Faker()
faker.unique.enable(faker::address)
val excludedCountries = listOf(
"Afghanistan",
"Albania",
"Algeria",
"American Samoa",
"Andorra",
"Angola"
)
faker.unique.exclude<Address>("country", excludedCountries)
// in addition to generating unique values
// this will not generate any of the excluded countries as well
faker.address.country()
This is only applicable when the whole category, i.e. Address
is enabled for unique generation
of values.
faker.address.unique.country() // will still generate unique values, but won't consider exclusions if any
Faker
can be configured to use a localized dictionary file instead of the default en
locale.
val fakerConfig = FakerConfig.builder().create {
locale = "nb-NO"
}
val faker = Faker(fakerConfig)
val city1 = faker.address.city() // => Oslo
List of available locales (clickable):
ar
bg
ca
ca-CAT
da-DK
de
de-AT
de-CH
ee
en
- defaulten-AU
en-au-ocker
en-BORK
en-CA
en-GB
en-IND
en-MS
en-NEP
en-NG
en-NZ
en-PAK
en-SG
en-TH
en-UG
en-US
en-ZA
es
es-MX
fa
fi-FI
fr
fr-CA
fr-CH
he
hy
id
it
ja
ko
lv
nb-NO
nl
no
pl
pt
pt-BR
ru
sk
sv
th
tr
uk
vi
zh-CN
zh-TW
Using a non-default locale will replace the values in some of the providers with the values from localized dictionary.
val fakerConfig = FakerConfig.builder().create {
locale = "es"
}
val faker = Faker(fakerConfig)
faker.address.city() // => Barcelona
Note that if the localized dictionary file does not contain a category (or a parameter in a category) that is present in the default locale, then non-localized value will be used instead.
val faker = Faker()
faker.gameOfThrones.cities() // => Braavos
val fakerConfig = FakerConfig.builder().create {
locale = "nb-NO"
}
val localizedFaker = Faker(fakerConfig)
// `game_of_thrones` category is not localized for `nb-NO` locale
localizedFaker.gameOfThrones.cities() // => Braavos
Although this lib was created with Kotlin in mind it is still possible to use from a Java-based project thanks to great Kotlin-to-Java interop.
Configuring Faker
:
FakerConfig fakerConfig = FakerConfigBuilder.create(FakerConfig.builder(), fromConsumer(builder -> {
builder.setRandom(new Random(42));
builder.setLocale("en-AU");
}));
If builder
parameter is not called with help of fromConsumer
method,
then explicit return should be specified:
FakerConfig fakerConfig = FakerConfigBuilder.create(FakerConfig.builder(), builder -> {
builder.setRandom(new Random(42));
builder.setLocale("en-AU");
return Unit.INSTANCE;
});
Calling Faker
methods:
new Faker(fakerConfig).getName().firstName(); // => John
Command line application can be used for a quick lookup of faker functions. See faker-bot README for installation and usage details.
Below is the list of available providers that correspond to the dictionary files found in core/locales/en
Note that not all (although most) of the providers and their functions are implemented at this point.
For more details see the particular .md
file for each provider below.
List of available providers (clickable):
- Address
- Ancient
- Animal
- App
- Appliance
- AquaTeenHungerForce
- Artist
- BackToTheFuture
- Bank
- Basketball
- Beer
- BojackHoreseman
- Book
- BossaNova
- BreakingBad
- Buffy
- Business
- Cannabis
- Cat
- Chiquito
- ChuckNorris
- Code
- Coffee
- Coin
- Color
- Commerce
- Community
- Company
- Compass
- Computer
- Construction
- Cosmere
- CryptoCoin
- CultureSeries
- Currency
- DcComics
- Demographic
- Dessert
- Device
- Dog
- Dota
- DragonBall
- DrWho
- DumbAndDumber
- Dune
- Educator
- ElderScrolls
- ElectricalComponents
- ESport
- Fallout
- FamilyGuy
- File
- Finance
- Food
- Football
- FreshPriceOfBelAir
- Friends
- FunnyName
- Game
- GameOfThrones
- Gender
- GhostBusters
- GratefulDead
- GreekPhilosophers
- Hacker
- HalfLife
- HarryPotter
- Heroes
- HeroesOfTheStorm
- HeyArnold
- Hipster
- HitchhikersGuideToTheGalaxy
- Hobbit
- Horse
- House
- HowIMetYourMother
- IdNumber
- IndustrySegments
- Internet
- Invoice
- Job
- KPop
- LeagueOfLegends
- Lebowski
- LordOfTheRings
- Lorem
- Lovecraft
- Markdown
- Marketing
- Measurement
- MichaelScott
- Military
- Movie
- Music
- Myst
- Name
- Nation
- NatoPhoneticAlphabet
- NewGirl
- OnePiece
- Opera
- Overwatch
- ParksAndRec
- Phish
- PhoneNumber
- Pokemon
- PrincessBride
- ProgrammingLanguage
- Quote
- Rajnikanth
- Relationship
- Restaurant
- RickAndMorty
- RockBand
- Rupaul
- Science
- Seinfeld
- Shakespeare
- SiliconValley
- Simpsons
- SlackEmoji
- SonicTheHedgehog
- Source
- SouthPark
- Space
- Stargate
- StarTrek
- StarWars
- StrangerThings
- Stripe
- Subscription
- Superhero
- SuperSmashBros
- SwordArtOnline
- Team
- TheExpanse
- TheITCrowd
- TheThickOfIt
- TwinPeaks
- UmphreysMcgee
- University
- Vehicle
- VentureBros
- Verbs
- VForVendetta
- Witcher
- WorldCup
- WorldOfWarcraft
- Yoda
- Zelda
It is possible to generate a random instance of any class with Faker().randomProvider
. For example:
class Foo(val a: String)
class Bar(val foo: Foo)
class Test {
@Test
fun test() {
val faker = Faker()
val foo: Foo = faker.randomProvider.randomClassInstance()
val bar: Bar = faker.randomProvider.randomClassInstance()
}
}
There are the following rules when creating a random instance of a class:
- The constructor with the least number of arguments is used
kotlin.collection.*
andkolin.Array
types in the constructor are not supported at the moment
Prior to version 1.0:
Faker
was a singleton.- Random seed was provided through
Faker.Config
instance. - Locale was provided as parameter to
init()
function. - Provider functions were function literals. If
invoke()
was explicitly specified, then it will have to be removed (See below.)
After version 1.0:
Faker
is a class.- Configuration (rng, locale) is set with
FakerConfig
class. An instance ofFakerConfig
can be passed toFaker
constructor. - Provider functions are no longer function literals. Explicit calls to
invoke()
will throw compilation error.
- // prior to version 1.0
- Faker.Config.random = Random(42)
- Faker.init(locale)
- Faker.address.city()
- // or with explicit `invoke()`
- Faker.address.country.invoke()
+ // since version 1.0
+ // locale and random configuration is set with `FakerConfig` class (See Usage in this readme)
+ val faker = Faker(fakerConfig)
+ faker.address.city()
+ // explicit calls to `invoke()` have to be removed
+ faker.address.country()
Apart from changes to configuring locale and random seed
and instantiating Faker
through constructor instead of using a singleton instance (see kotlin examples),
the main difference for java users is that provider functions are no longer function literals,
therefore calls to invoke()
operator will have to be removed and
getters replaced with function calls.
- // prior to version 1.0
- Faker.init(locale);
- Faker.getAddress().getCity().invoke();
+ // since version 1.0
+ Faker faker = new Faker(fakerConfig);
+ // note `city()` function is called instead of getter
+ // and no call to `invoke()` operator
+ faker.getAddress().city();
Builds and deploys to bintray are automated with travis-ci through usage of git tags.
Patches/hotfixes versions are automatically bumped on every push to master and do not require any user interactions.
Major and minor versions need to be bumped manually through a tag with the next release version that has to follow the
v<major>.<minor>.<patch>
pattern, and the tag has to be pushed to origin along with the changes.
Creating the tag can be either done manually with git tag
or by using gradlew tag -Prelease -PbumpComponent=${comp}
where comp
can be one of the following values: major
, minor
, or patch
.
Feel free to submit a pull request and/or open a new issue if you would like to contribute.
Many thanks to these awesome tools that help us in creating open-source software:
This code is free to use under the terms of the MIT licence. See LICENCE.md.