SirWellington / alchemy-generator

Generators for Data and other Common Objects

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Alchemy Generator

"More Data => Better tests"

Build Status Maven Central Version

Purpose

Part of the Alchemy Series, this library makes it easier to test your code by providing generators for common Objects and Data.

Introducing randomized data to tests helps improve test quality by assuring that your code can work over a wide range of data values, and not just what you hard-code in. It also increases confidence that code will work in a variety of circumstances.

Download

To use, simply add the following maven dependency.

Release

<dependency>
	<groupId>tech.sirwellington.alchemy</groupId>
	<artifactId>alchemy-generator</artifactId>
	<version>2.4.1</version>
</dependency>

API

Examples use static imports Specifically, tech.sirwellington.alchemy.generator.Generators.one()

Numbers

tech.sirwellington.alchemy.generator.NumberGenerators

Integers

//A number in the range [-50, 50)
int anInteger = integers(-50, 50).get();

Longs

//Get any positive long
long somePositiveNumber = positiveLongs().get();

//alternative way to get a single value
somePositiveNumber = one(positiveLongs());

Doubles

//A double in the range [0.1, 1999.0]
AlchemyGenerator<Double> doubleGenerator = doubles(0.1, 1999.0);
for(int i = 0; i < 100; ++i)
{
	LOG.info("Received double {}", doubleGenerator.get());
}

Strings

tech.sirwellington.alchemy.generator.StringGenerators

Alphabetical

Uses the Latin Alphabet, a-z | A-Z

String alphabetical = alphabeticStrings().get();

Alphanumeric

Uses the Latin Alphabet, and numbers 1-9.

String alphanumeric = one(alphanumericStrings());

Hexadecimal

String hex = hexadecimalString(32).get();

Any String

These strings may have unicode characters as well. These are great for testing against international character sets as well.

String anyCharacterString = strings(30).get();
assertThat(anyCharacterString.length(), is(30));

UUIDs

Guaranteed unique strings

int amount = one(smallPositiveIntegers());
AlchemyGenerator<String> uuids = uuids();
Set<String> ids = listOf(uuids, amount);

//Check for uniqueness
assertThat(ids.size(), is(amount));

From Fixed Set

Strings can be generated from a preselected set of String values.

//The generated strings can only be one of the supplied ones.
String stringFromList = stringsFromFixedList("one", "something else", "Java").get();

Binary

tech.sirwellington.alchemy.generator.BinaryGenerators

byte[]

byte[] someBinary = one(BinaryGenerators.binary(10_000));
assertThat(someBinary.length, is(10_000));

ByteBuffer

ByteBuffer buffer = one(BinaryGenerators.byteBuffers(1_000));
assertThat(buffer, notNullValue());

Collections

tech.sirwellington.alchemy.generator.CollectionGenerators

Lists

List<String> randomStrings = listOf(alphabeticStrings(20), 100);
List<Integer> ages = listOf(integers(1, 100));

Maps

AlchemyGenerator<String> names = alphabeticalStrings();
AlchemyGenerator<Integer> ages = integers(1, 100);

int numberOfPeople = 50;
Map<String,Integer> ages = mapOf(names, ages, numberOfPeople);

Dates and Times

Generators for Instant type:


`tech.sirwellington.alchemy.generator.TimeGenerators`
AlchemyGenerator<Instant> alwaysNow = presentInstants();
Instant timeInThePast = pastInstants().get();
Instant timeInTheFuture = futureInstants().get();

Generators for Date type:


`tech.sirwellington.alchemy.generator.DateGenerators` ```java AlchemyGenerator alwaysNow = presentDates(); Date dateInThePast = one(pastDates()); Date dateInTheFuture = one(futureDates()); ```

Enums

tech.sirwellington.alchemy.generator.EnumGenerators

Sometimes you have an enum and you want to randomly access a value from it.

Alchemy Generator makes it simple:

enum Fruit
{
	APPLE,
	ORANGE,
	BANANA,
	GUAVA
}

You want a fruit, but don't care which one?

Fruit fruit = enumValueOf(Fruit.class).get();

People

Our code very often works people, and information about them tech.sirwellington.alchemy.generator.PeopleGenerators

String name = names().get();
int age = one(adultAges());
String phoneNumber = one(phoneNumberStrings());
String email = one(emails());

POJOs

POJOs are dumb data objects, that is they tend to contain no functionality other than getters/setters and value methods like equals(), hashCode(), and toString(). Alchemy Generator provides Automatic Generation of POJOs.

tech.sirwellington.alchemy.generator.ObjectGenerators

Let's say you have a class like

class Computer
{
    private int yearReleased;
    private String modelName;
    private double cost;
    private String manufacturer;
    private String operatingSystem;
}

Rather than creating Boiler Plate generation code for each pojo, just use the pojos() generator.

@Test
public void testPurchaseOrder()
{
    Computer computer = one(pojos(Computer.class));
    shoppingCart.add(computer);
    shoppingCart.order();
    ...
}

Nested POJOs

The POJO generator contains a sophisticated recursive algorithm to generate complex hierarchies of POJOs, as long as it all eventually boils to down to primitive types (Integer, String, Double, Long, Date, etc).

class Developer
{
    private String name;
    private String alias;
    private int age;
    private Computer developerMachine;
    private Computer serverMachine;
}

Developer developer = one(pojos(Developer.class));

assertThat(developer, notNullValue());
assertThat(developer.name, not(isEmptyOrNullString()));
assertThat(developer.age, greaterThan(0));
assertThat(developer.developerMachine, notNullValue());
...

IMPORTANT: There can be NO circular references. A Computer cannot contain a Developer at the same time that Developer contains Computer. This would cause a StackOverflow.

Collections

tech.sirwellington.alchemy.generator.CollectionGenerators

The POJO Generator also handles Generic enum, List, Set, and Map types that contain either Primitive Types, or other POJOs.

class City
{
    private String name;
    private long population;
    private List<Developer> developersInTown;
    private Map<String, Building> addressDirectory;
}

City sampleCity = one(pojos(City.class));

IMPORTANT: Complicated and nested data structures increase the amount of time of Object Generation, since for each Collection, the algorithm must recurse to generate more POJOs for the collection. This library was designed for Unit Testing purposes, however, and so performance is less important.

Networking

tech.sirwellington.alchemy.generator.NetworkGenerators

NetworkGenerators contains generation code for Networking related concepts and data, such as URLs, hostnames, ports, etc.

URLs

URL httpUrl = one(httpUrls());
URL httpsUrl = one(httpsUrls());
URL tcpUrl = one(urlsWithProtocol("tcp"));

Hostnames

Create Network names in accordance to standards.

String hostname = one(localNetworkNames());
hostname = one(fullyQualifiedDomainNames());

Ports

int port = one(ports());

MAC Addresses

Coming Soon.

Requirements

  • Java 8
  • Maven

Building

This project builds with maven. Just run a mvn clean install to compile and install to your local maven repository

Feature Requests

Feature Requests are definitely welcomed! Please drop a note in Issues.

License

This Software is licensed under the Apache 2.0 License

http://www.apache.org/licenses/LICENSE-2.0

About

Generators for Data and other Common Objects

License:Apache License 2.0


Languages

Language:Kotlin 96.6%Language:Java 3.4%