Giter Site home page Giter Site logo

qala-io / datagen Goto Github PK

View Code? Open in Web Editor NEW
60.0 7.0 4.0 242 KB

Java lib that generates random data (numbers, strings, dates) - mostly to facilitate Randomized Testing.

Home Page: http://qala.io/blog/randomized-testing.html

License: Apache License 2.0

Java 100.00%
java testing randomization random-number-generators random-data-generation random-generation random

datagen's Introduction

Datagen

Maven Central

Java library to generate random data (numbers, strings, dates) - to facilitate Randomized Testing. Randomization may be used to improve coverage, but it can also speed up the process of writing & running tests. Some use cases for randomization:

  • Combinatorial Testing - helps reducing the number of test cases you need to write and run
  • Fighting with Unique Constraints - do you have a test that registers users with unique username? And the next time you run the test it fails because such user already exists..
  • "Wow, I didn't know about that" effect - sometimes randomization may discover tricky cases that you couldn't think of.
  • Which one to pick? - often when choosing test data there is no clear winner of what value to pick. Randomization helps with that and ensures we're not prone to Pesticides Effect.

Example

import java.time.OffsetDateTime;

import static io.qala.datagen.RandomDate.beforeNow;
import static io.qala.datagen.RandomShortApi.*;

public class Dog {
    private String name;
    private OffsetDateTime timeOfBirth;
    private double weight;
    private double height;

    public static Dog random() {
        Dog dog = new Dog();
        dog.name = alphanumeric(1, 100);
        dog.timeOfBirth = nullOr(beforeNow().offsetDateTime());
        dog.weight = positiveDouble();
        dog.height = positiveInteger();
        return dog;
    }
}
@Alphanumeric(min = 2, max = 29, name = "middle value")
@Alphanumeric(length = 30, name = "max boundary")
@English(max=30)
void eachAnnotationInvokesTheTestOnceAndPassesParameters(String value, String name) {
    assertTrue(value.length() >= 1 && value.length() <= 31, "Failed case: " + name);
}

@RandomInt(min = 1, name = "greater than zero")
@RandomInt(max = -1, name = "less than zero")
void zeroInt_isNotPassed(int param, String name) {
    assertNotEquals(0, param, "Failed case: " + name);
}

Strings

import static io.qala.datagen.RandomValue.*;
import static io.qala.datagen.StringModifier.Impls.*;
import static io.qala.datagen.RandomShortApi.*;
Flexible API Short API Result
length(10).english() english(10) "DcRZUNPrED"
between(1, 10).alphanumeric() alphanumeric(0, 10) "zG9G"
between(1, 10).numeric() numeric(1, 10) "7167162"
length(5).unicode() unicode(5) "䂞ꂣ뢧䯺婜"
length(5).string("A_ B") " _B B"
length(10).with(specialSymbol()).english() "hOzKEV#iWv"
length(10).with(oneOf("_,")).english() "dwei,cNTfW"
length(5).with(spaces()).numeric() "874 9 "
length(3).with(spaceLeft()).english() " mT"
length(4).with(spacesRight(2)).english() "hF "
length(10).with(prefix("BLAH")).numeric() "BLAH453677"
between(1, 10).alphanumerics(4) ["cvA", "mTMDj0", "N", ""]
mixedCase("blah") "bLaH"

Nulls & Blanks

API Result
nullOrEmpty() "", null
nullOrBlank() "", " ", null
nullOr(10L) null, 10L
nullOr("string") null, "string"
blankOr("string") "", " ", null, "string"

Repeats

import static io.qala.datagen.RandomString.Type.*;
import static io.qala.datagen.RandomValue.*;
import static io.qala.datagen.Repeater.*;

repeat(length(4), NUMERIC).string("-").times(4)`

Result: "9338-8349-6940-7714"

Numbers

import static io.qala.datagen.RandomValue.*;
import static io.qala.datagen.RandomShortApi.*;
Flexible API Short API Result
between(0, 100).integer() integer(100) 89
between(-100, 100).integer() integer(-100, 100) -19
positiveInteger() 3432145
Long() 7635811362052252913
negativeDouble() -8.9946257128846746E18

Collections/Arrays

import static io.qala.datagen.RandomElements.*;
import static io.qala.datagen.RandomShortApi.*;
Flexible API Short API Result
from("A", "B", "C", "D").sample() sample("A", "B", "C") "C"
from("A", "B", "C", "D").sample(2) sampleMultiple(2, "A", "B", "C") ["B", "A"]
from("A", "B").sampleWithReplacement(3) ["A", "A", "B"]
from("A", "B", "C").shuffled() shuffled("A", "B", "C") ["C", "A", "B"]

Java Date

import static io.qala.datagen.RandomValue.*;

SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
between(f.parse("2015-01-01"), f.parse("2016-01-01")).date();

Result: 2015-11-30T08:33:20.349

Java8 DateTime

// Requires Java8 and qala-datagen-java8types dependency
import static io.qala.datagen.RandomDate.*;
API Result
plusMinus100Years().zonedDateTime() 1937-09-27T01:16:15.925440485+01:00[Europe/Belgrade]
since(yearAgo()).instant() 2015-11-30T08:39:28.397051483Z
before(now()).instant() -241279778-02-14T16:07:18.061693370Z
between(yearsAgo(2), startOfMonth()).localDate() 2014-09-30

Booleans

import static io.qala.datagen.RandomShortApi.*;
API Result
bool() or weighedTrue(0.5) false
bools(4) [false, true, true, false]
nullableBool() Boolean.TRUE

Functions (for Java8 lambdas)

import static io.qala.datagen.RandomShortApi.*;
Person person = new Person();

callOneOf(() -> person.firstName = english(5),
          () -> person.lastName = english(5));

Result: Person[null, "PDGRq"]

callNoneOrMore(() -> person.firstName = english(5),
               () -> person.lastName = english(5));

Result: Person[null, null]

callOneOrMore(() -> person.firstName = english(5),
              () -> person.lastName = english(5));

Result: Person["LjxYh", "UXoBt"]

Other

Special thanks

To keep the lib tiny and get rid of extra dependencies (there are no transitive dependencies) some of the code was borrowed from these libs: Commons Lang, Commons Math. Hail to open source!

datagen's People

Contributors

ctapobep avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

datagen's Issues

Add support for generating random URLs

It would be great to have a method for generating random URLs.

We can start from just a random string with arbitrary length and later add API for control possible protocols, domain zones, how many domains/subdomains it could have, port ranges, number of segments, etc

sampleMultiple: possible incorrect javadoc comments

/**
* Returns multiple random elements from the specified collection.
*
* @param toSampleFrom the population of the elements you'd like to get a random value from
* @return 0 or more elements of the specified collection, elements don't repeat
*/
public static <T> List<T> sampleMultiple(Collection<T> toSampleFrom) {
return sampleMultiple(integer(toSampleFrom.size()), toSampleFrom);
}
/**
* Returns multiple random elements from the specified collection.
*
* @param toSampleFrom the population of the elements you'd like to get a random value from
* @return a random element from the collection
*/
public static <T> Set<T> sampleMultiple(Set<T> toSampleFrom) {
return new HashSet<T>(sampleMultiple((Collection<T>) toSampleFrom));
}

I think that there 2 errors:

  • Set<T> sampleMultiple has an incorrect comment "@return a random element from the collection" because it doesn't return an element but a set of elements
  • List<T> sampleMultiple mentions that "elements don't repeat" but it returns a List that could have duplicates. Perhaps, this is addressed to Set<T> sampleMultiple?

Generate a string with specified separators

I need to generate a string that could consist from words. I'm trying the following:

length(10).with(oneOf(" ,")).english()

but sometimes it generates strings that start or end with space or comma. I'm looking to a way of avoiding it. Would it be possible to also specify a separator between words?

upTo() may fail with IllegalArgumentException: Min [0] cannot be larger than max [-1]

The given code

String invalidName = upTo(10).with(oneOf('%_')).english()

could fails with the exception:

java.lang.IllegalArgumentException: Min [0] cannot be larger than max [-1]

	at io.qala.datagen.RandomValue.<init>(RandomValue.java:23)
	at io.qala.datagen.RandomValue.upTo(RandomValue.java:36)
	at io.qala.datagen.StringModifier$Impls$1.modify(StringModifier.java:79)
	at io.qala.datagen.RandomValue.applyStringModifiers(RandomValue.java:138)
	at io.qala.datagen.RandomValue.english(RandomValue.java:93)

I'm expecting that it shouldn't fail because I'm using an API that should handle such cases internally.

Consider moving example of nullOr() to a dedicated section

Example of nullOr("string") that is returning "string" looks weird in Collections/Arrays section. My first impression was that it should be in the section about strings.

I suggest to

  1. add example for nullOr("string") to the section about strings (for completeness)
  2. remove this example from the Collections/Arrays section
  3. introduce a dedicated section for nullOr() with different examples (to demonstrate that it uses generics and may accepts any types, not only strings)

Examples should clearer say about whether values included/excluded in a range

It's not clear from examples whether arguments of the methods like between(), upTo() and length() are treating as open or closed ranges.

In other words, between(1, 10).numeric() is returning strings of length (1, 10) or [1, 10].

Could we clarify this moment? And also in the javadoc comments (if this information is missing).

Provide a way of generating a list of values with specific characteristics

We have many methods for generating just a single value but it would be super useful to provide an API for generating a list (or set) of value with some characteristics.

Maybe something like this:

List<Integer> ints = RandomList.ofLength(between(1, 5)).withValues(between(1, 10));

Another option is to leverage Java 8 streams API and have a method that takes a function that produce some value and invokes this function N times.

Rename package for JUnit Jupiter support

Since your support for JUnit 5 is actually support for the JUnit Jupiter programming model, I highly recommend that you rename the io.qala.datagen.junit5 package to io.qala.datagen.junit.jupiter in order to avoid conflicts with future versions of JUnit (e.g., JUnit 6's support for JUnit Jupiter).

No way to generate a string with arbitrary length

In my unit test I need to generate some string. I don't have any requirements to it, just some string. I didn't find a method for that, all the existing ways require me to specify a length. I'm tried the following:

String expectedName = nullOr(between(1, positiveInteger()).unicode());

but it makes my test very slow and failing with OutOfMemoryError:

java.lang.OutOfMemoryError: Java heap space

	at io.qala.datagen.adaptors.CommonsLang3RandomStringUtils.random(CommonsLang3RandomStringUtils.java:251)
	at io.qala.datagen.adaptors.CommonsLang3RandomStringUtils.random(CommonsLang3RandomStringUtils.java:163)
	at io.qala.datagen.adaptors.CommonsLang3RandomStringUtils.random(CommonsLang3RandomStringUtils.java:143)
	at io.qala.datagen.adaptors.CommonsLang3RandomStringUtils.random(CommonsLang3RandomStringUtils.java:69)
	at io.qala.datagen.RandomValue.unicode(RandomValue.java:103)
	at ru.mystamps.web.util.extractor.SiteParserTest.toStringShouldReturnName(SiteParserTest.java:99)

Could we have a method for generating a string with some random length (but not too high to still have fast tests)?

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.