Git Product home page Git Product logo

alchemy-generator's Introduction

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

alchemy-generator's People

Contributors

sirwellington avatar

Stargazers

 avatar

Watchers

 avatar

alchemy-generator's Issues

Generate POJOs

As a Developer, I would love to have an AlchemyGenerator that inspected a POJO at runtime and populated it with fake data for me.

Filename generator

Generate valid filenames with valid and common text-based extension types.

Add a Byte generator

Returns a single byte at a time.

Byte singleByte = one(BinaryGenerators.bytes());

Add DateGenerators.dateBetween(begin,end)

This Generator produces Dates between a specified date.

Date startDate  = ...;
Date endDate = ...;

AlchemyGenerator<Date> datesBetween = DateGenerators.dateBetween(startDate, endDate);

Address Generator

Addresses are commonly generated for test purposes. Care should be taken to generate correct addresses, and not just random strings.

Add TimeGenerators.timeBetween(begin,end)

This Generator produces Instants between a specified time.

Instant startTime  = ...;
Instant endTime = ...;

AlchemyGenerator<Instant> timesBetween = TimeGenerators.timeBetween(startTime, endTime);

Fix Pojo Generator issue with Bytes

This exception keeps popping up on Classes with a Byte field:

java.lang.NoSuchMethodException: java.lang.Byte.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_66]
    at java.lang.Class.getDeclaredConstructor(Class.java:2178) ~[na:1.8.0_66]
    at tech.sirwellington.alchemy.generator.ObjectGenerators.instantiate(ObjectGenerators.java:216) [alchemy-generator-1.4-SNAPSHOT.jar:na]
    at tech.sirwellington.alchemy.generator.ObjectGenerators.canInstantiate(ObjectGenerators.java:192) [alchemy-generator-1.4-SNAPSHOT.jar:na]
    at tech.sirwellington.alchemy.generator.ObjectGenerators.pojos(ObjectGenerators.java:153) [alchemy-generator-1.4-SNAPSHOT.jar:na]
    at tech.sirwellington.alchemy.generator.ObjectGenerators.pojos(ObjectGenerators.java:147) [alchemy-generator-1.4-SNAPSHOT.jar:na]
    at tech.sirwellington.alchemy.generator.ObjectGenerators.determineGeneratorFor(ObjectGenerators.java:333) [alchemy-generator-1.4-SNAPSHOT.jar:na]
    at tech.sirwellington.alchemy.generator.ObjectGenerators.injectField(ObjectGenerators.java:266) [alchemy-generator-1.4-SNAPSHOT.jar:na]
    at tech.sirwellington.alchemy.generator.ObjectGenerators.tryInjectField(ObjectGenerators.java:253) [alchemy-generator-1.4-SNAPSHOT.jar:na]
    at tech.sirwellington.alchemy.generator.ObjectGenerators.lambda$pojos$31(ObjectGenerators.java:180) [alchemy-generator-1.4-SNAPSHOT.jar:na]

Name Generators from Dictionary

We don't really want this library making calls to a database or another external system, however it would be nice to have it load actual names from a resource file.

New String Generators

  • email Generator
  • Name Generator
  • Filename Generator
  • Phone Number Generator
  • ToString Generator
  • Address Generator

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.