Git Product home page Git Product logo

kotlin-faker's Introduction

fake-logo

kotlin-faker

Build Status Version Badge Coverage Status Issues Badge Awesome Kotlin Badge Licence Badge

Generates realistically-looking fake data

ToC

About

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.

Comparison with other jvm-based faker libs

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

Usage

Downloading

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

Using the latest hotfix release

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.

Generating data

val faker = Faker()

faker.name.firstName() // => Ana
faker.address.city() // => New York

Configuring Faker

Default configuration

If no FakerConfig instance is passed to Faker constructor then default configuration will be used:

  • locale is set to en
  • random is seeded with a pseudo-randomly generated number.
  • uniqueGeneratorRetryLimit is set to 100

Deterministic Random

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

Generating unique values

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

Localized dictionary

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
Available Locales
List of available locales (clickable):

  • ar
  • bg
  • ca
  • ca-CAT
  • da-DK
  • de
  • de-AT
  • de-CH
  • ee
  • en - default
  • en-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

Java interop

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

CLI

Command line application can be used for a quick lookup of faker functions. See faker-bot README for installation and usage details.

Data Providers

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):

Generating a random instance of any class

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.* and kolin.Array types in the constructor are not supported at the moment

Migrating to 1.0

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 of FakerConfig can be passed to Faker constructor.
  • Provider functions are no longer function literals. Explicit calls to invoke() will throw compilation error.

For kotlin users

- // 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()

For java users

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();

Build and Deploy

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.

Contributing

Feel free to submit a pull request and/or open a new issue if you would like to contribute.

Thanks

Many thanks to these awesome tools that help us in creating open-source software:
Intellij IDEA YourKit Java profiler

Licence

This code is free to use under the terms of the MIT licence. See LICENCE.md.

kotlin-faker's People

Contributors

serpro69 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.