Nothing Special   »   [go: up one dir, main page]

Skip to content

Releases: instancio/instancio

5.2.0

02 Dec 23:11
Compare
Choose a tag to compare

What's Changed

New Features

wordTemplate() spec that supports noun, verb, adjective, and adverb placeholders (#1220)

A spec for generating text based on a template containing placeholders, such as ${noun}, ${verb}, ${adjective}, and ${adverb}.

Example:

record Company(String website) {}

List<Company> companies = Instancio.ofList(Company.class)
    .size(3)
    .generate(field(Company::website), gen -> gen.text().wordTemplate("${adjective}-${noun}.com"))
    .create();

// Sample output:
[[Company[website=global-bidder.com],
  Company[website=independent-beat.com],
  Company[website=promotional-clock.com]]

The placeholders are case-sensitive and support three case styles for the output:

  • ${noun} - Outputs a lowercase word e.g. "cat"
  • ${Noun} - Outputs a capitalised word e.g. "Cat"
  • ${NOUN} - Outputs an uppercase word e.g. "CAT"

Throw an error by default if applyFeed() has unmapped feed properties (#1225)

This is a potential breaking change to an experimental API. The original behaviour can restored by the new setting Keys.ON_FEED_PROPERTY_UNMATCHED which can be used to ignore unmapped feed properties.

Bug Fixes

Only report the initial seed for @InstancioSource tests (#1223)


  • wordTemplate() spec that supports noun, verb, adjective, and adverb placeholders by @armandino in #1220
  • Bump com.fasterxml.jackson.core:jackson-databind from 2.18.1 to 2.18.2 by @dependabot in #1222
  • Bump version.kotlin from 2.0.21 to 2.1.0 by @dependabot in #1221
  • Bug fix: only report the initial seed for @InstancioSource tests by @armandino in #1223
  • Throw an error by default if applyFeed() has unmapped feed properties by @armandino in #1225
  • Bump org.apache.felix:maven-bundle-plugin from 5.1.9 to 6.0.0 by @dependabot in #1224
  • Bump nl.jqno.equalsverifier:equalsverifier-nodep from 3.17.3 to 3.17.4 by @dependabot in #1227
  • Bump com.puppycrawl.tools:checkstyle from 10.20.1 to 10.20.2 by @dependabot in #1226

Full Changelog: instancio-parent-5.1.0...instancio-parent-5.2.0

5.1.0

25 Nov 02:39
Compare
Choose a tag to compare

What's Changed

New Features

Add as(Function) method to the oneOf() generator spec (#1212)

Sample usage:

class Pojo {
  JsonNullable<String> jsonNullableString;
}

Pojo pojo = Instancio.of(Pojo.class)
        .generate(field("jsonNullableString"), gen -> gen.oneOf("foo", "bar").as(JsonNullable::of))
        .create();

Related to:

Support for generating words (adjectives, adverbs, nouns, verbs) (#1213)

The word() spec can generates words, including nouns, verbs, adjectives, and adverbs.

Example:

record Example(String word) {}

Example example = Instancio.of(Example.class)
    .generate(field(Example::word), gen -> gen.text().word().noun())
    .create();

// Sample output: Example[word=achievement]

Phrases or sentences can be constructed using a Supplier:

record Company(String website) {}

Supplier<String> websiteSupplier = () -> String.format(
    "https://www.%s-%s.com",
    Instancio.gen().text().word().adjective().get(),
    Instancio.gen().text().word().noun().get());

List<Company> companies = Instancio.ofList(Company.class)
    .size(3)
    .supply(field(Company::website), websiteSupplier)
    .create();

// Sample output:
[[Company[website=https://www.global-bidder.com],
  Company[website=https://www.independent-beat.com],
  Company[website=https://www.promotional-clock.com]]

Bug Fixes

Apply scopes when converting root() to all(Class) for setModel() (#1217)


Full Changelog: instancio-parent-5.0.2...instancio-parent-5.1.0

5.0.2

12 Sep 17:26
Compare
Choose a tag to compare

What's Changed

  • Support for quoted CSV values in feeds by @berkayerten in #1142
  • Bug fix: convert root() to all(Class) selector when using setModel() (#1159) by @armandino in #1160
  • Dependency upgrades

New Contributors

Full Changelog: instancio-parent-5.0.1...instancio-parent-5.0.2

5.0.1

28 Jul 19:55
Compare
Choose a tag to compare

What's Changed

  • Bug fix: error applying feed specs to primitive fields by @armandino in #1125

Full Changelog: instancio-parent-5.0.0...instancio-parent-5.0.1

5.0.0

23 Jul 23:35
Compare
Choose a tag to compare

What's Changed

Breaking changes

Renamed classes:

  • org.instancio.InstancioOfClassApi to InstancioClassApi
  • org.instancio.InstancioOfCollectionApi to InstancioCollectionsApi

Breaking changes to experimental APIs

1. Removed the deprecated instancio-quickcheck module

2. Replaced org.instancio.Gen with org.instancio.Instancio.gen()

// Before
import org.instancio.Gen;

int n = Gen.ints().range(1, 10).get();

// Now
import static org.instancio.Instancio.gen;

int n = gen().ints().range(1, 10).get();

3. Removed method org.instancio.generator.ValueSpec.toModel():

Model<Integer> model = gen().ints().range(1, 10)
        .toModel(); // toModel() method no longer available

The above can still be achieved using Instancio.of() API:

Model<Integer> model = Instancio.of(Integer.class)
        .generate(Select.root(), gen -> gen.ints().range(1, 10))
        .toModel();

4. Renamed CartesianProductApi class to InstancioCartesianProductApi

5. Renamed CsvGeneratorSpec.separator() method to delimiter()

New Features

Feed API for generating data from an external resource (CSV or JSON)

Example data file: persons.csv

firstName,lastName,age
John,Doe,21
Alice,Smith,34
# ...
List<Person> person = Instancio.ofList(Person.class)
    .applyFeed(all(Person.class), feed -> feed.ofResource("persons.csv"))
    .create();

// Output:
// [Person[firstName="John", lastName="Doe", age=21],
//  Person[firstName="Alice", lastName="Smith", age=34],
//  ...]

A feed can also be defined as an interface, which offers additional features and allows
the feed to be reused across multiple tests.

@Feed.Source(name = "persons.csv")
interface PersonFeed extends Feed {

  FeedSpec<String> firstName(); // maps to 'firstName' property in the data file

  @DataSpec("lastName") // maps to `lastName` property in the data file
  FeedSpec<String> surname();

  @TemplateSpec("${firstName} ${lastName}")
  FeedSpec<String> fullName();

  @FunctionSpec(params = "age", provider = DateOfBirthCalculator.class)
  FeedSpec<LocalDate> dateOfBirth();

  class DateOfBirthCalculator implements FunctionProvider {
    LocalDate toDateOfBirth(int age) {
      return LocalDate.now().minusYears(age);
    }
  }
}

// Sample usage
List<Person> person = Instancio.ofList(Person.class)
    .applyFeed(all(Person.class), feed -> feed.of(PersonFeed.class))
    .create();

// Output:
// [Person[firstName="John", surname="Doe", fullName="John Doe", age=21, ...],
//  ...]

More info: https://www.instancio.org/user-guide/#data-feeds

@Given annotation for injecting test fields and parameters

@ExtendWith(InstancioExtension.class)
class ExampleTest {

    @Given
    private String randomStringField;

    @Test
    void example1(@Given List<String> randomList) {
        assertThat(randomStringField).isNotBlank();
        assertThat(randomList).isNotEmpty();
    }

    @ValueSource(strings = {"foo", "bar"})
    @ParameterizedTest
    void example2(String fooOrBar, @Given long randomLong) {
        assertThat(fooOrBar).isIn("foo", "bar");
        assertThat(randomLong).isPositive();
    }
}

The @Given annotation can also be used with a custom GivenProvider implementation, e.g.

    @Given(CustomStringProvider.class)
    private String customString;

Additionally, the @Given annotation can be used to define custom annotations:

@Given(NumericStringProvider.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@interface NumericString {

    int length();

    class NumericStringProvider implements GivenProvider {
        @Override
        public Object provide(ElementContext context) {
            NumericString numericString = context.getAnnotation(NumericString.class);
            return context.random().digits(numericString.length());
        }
    }
}

// Sample usage:
@ExtendWith(InstancioExtension.class)
class ExampleTest {

    @Test
    void example(@NumericString(length = 5) String digits) {
        assertThat(digits).hasSize(5).containsOnlyDigits();
    }
 }

More info: https://www.instancio.org/user-guide/#given-injection

@InstancioSource enhancements

  • Added samples attribute - specifies the number of times a test method annotated with @InstancioSource will run.
  • Added Keys.INSTANCIO_SOURCE_SAMPLES setting - configures the default number of samples.

By default, starting from version 5.0.0, tests annotated with @InstancioSource will run 100 times. This is a potentially breaking change, as previously, they were executed only once.

Example:

@ExtendWith(InstancioExtension.class)
class ExampleTest {

    @ParameterizedTest
    @InstancioSource
    void example1(Foo foo) {
        // will run 100 times with different instances of Foo
    }

    @ParameterizedTest
    @InstancioSource(samples = 250)
    void multipleArguments(Bar bar, Baz baz) {
        // will run 250 times with different instances of Bar and Baz
    }
}

Support for generating intervals of various types, such as numeric and temporal values

Example: generate a list of vacations with start/end dates.

record Vacation(LocalDate start, LocalDate end) {}
  • The first vacation should start on 2000-01-01.
  • Each vacation should last between 1-3 weeks.
  • There should be 12-15 months between vacations.
IntervalSupplier<LocalDate> vacationDates = Instancio.gen()
    .intervalStarting(LocalDate.of(2000, 1, 1))
    .nextStart((end, random) -> end.plusMonths(random.intRange(12, 15)))
    .nextEnd((start, random) -> start.plusWeeks(random.intRange(1, 3)))
    .get();

List<Vacation> vacations = Instancio.ofList(Vacation.class)
    .size(4)
    .supply(field(Vacation::start), vacationDates.start())
    .supply(field(Vacation::end), vacationDates.end())
    .create();

 // Sample output:
 // [Vacation[start=2000-01-01, end=2000-01-15],
 //  Vacation[start=2001-02-15, end=2001-03-08],
 //  Vacation[start=2002-03-08, end=2002-03-15],
 //  Vacation[start=2003-06-15, end=2003-07-06]]

Support for assign().valueOf() value with randomisation

Example: create a time period between 1 and 30 days, inclusive.

record TimePeriod(LocalDate start, LocalDate end) {}

TimePeriod period = Instancio.of(TimePeriod.class)
    .assign(Assign.valueOf(TimePeriod::start)
            .to(TimePeriod::end)
            .as((LocalDate start, Random random) -> start.plusDays(random.intRange(1, 30))))
    .create();

// Sample output: TimePeriod[start=2012-01-22, end=2012-01-30]

Support for Hibernate Validator constraints

New setting key: Keys.MAX_GENERATION_ATTEMPTS

Value spec for shuffling arrays and collections


Read more

4.8.1

26 Jun 02:25
Compare
Choose a tag to compare

What's Changed

Bug fix

  • Bug fix: error generating ZoneId on Java 17+ (#1077)

4.8.0

14 Jun 04:34
Compare
Choose a tag to compare

What's Changed

Breaking changes to experimental APIs

  • Renamed the Cartesian product creation method from list() to create()
Instancio.ofCartesianProduct(Class)
    .create(); // instead of list()

New Features

  • New top-level API withUnique(TargetSelector) for generating unique values for a given selector
List<Customer> customers = Instancio.ofList(Customer.class)
    .size(100)
    .withUnique(field(Customer::getId))
    .create();
  • New top-level as(Function) API for applying a Function to the result
    This is syntactic sugar that can be used, for example, to convert the result to JSON.

Sample usage:

String json = Instancio.of(Person.class).as(json());

// where json() is a user-defined function
static <T> Function<T, String> json() {
    return result -> new ObjectMapper()
            .writerWithDefaultPrettyPrinter()
            .writeValueAsString(result);
}
  • New setting Keys.STRING_CASE for specifying the case of generated strings (upper, lower, mixed):
Comment comment = Instancio.of(Comment.class)
    .withSetting(Keys.STRING_CASE, StringCase.MIXED)
    .create();

or globally using instancio.properties:

string.case=MIXED

Improvements

  • Improved handling of sealed abstract types.
    Instancio will use a random subclass as the subtype unless a specific subtype is specified explicitly.

  • Error message improvements

Deprecation

  • Deprecated the experimental instancio-quickcheck module

Full Changelog: instancio-parent-4.7.0...instancio-parent-4.8.0

4.7.0

27 May 02:32
Compare
Choose a tag to compare

What's Changed

New Features

New top-level APIs for creating blank objects

  • Instancio.createBlank(Class<T>)
  • Instancio.ofBlank(Class<T>)
  • setBlank(TargetSelector)

A blank object has the following properties:

  • null value fields (strings, numbers, dates)
  • blank nested POJOs
  • empty arrays and collections

For example:

Person person = Instancio.createBlank(Person.class);

// Output:
// Person[
//    name=<null>,
//    dateOfBirth=<null>,
//    phoneNumbers=[] // empty List
//    address=Address[street=<null>, city=<null>, country=<null>] // blank nested POJO
//]

Customising the object using the builder API:

Person person = Instancio.ofBlank(Person.class)
    .generate(field(Person::getPhoneNumbers), gen -> gen.collection().size(2))
    .set(field(Address::getCountry), "Canada")
    .set(field(Phone::getCountryCode), "+1")
    .create();

// Output:
// Person[
//    name=<null>,
//    dateOfBirth=<null>,
//    phoneNumbers=[Phone[countryCode=+1,number=<null>], Phone[countryCode=+1,number=<null>],
//    address=Address[street=<null>, city=<null>, country=Canada]
//]

String generator spec unicode() method

Comment comment = Instancio.of(Comment.class)
    .generate(field(Comment::getText), gen -> gen.string().unicode().length(30))
    .create();

// Sample output:
// Comment[text="﹩檘𤤑옖廪🕺样𝠴🪘𫢋荡𩓋喇䶷蝦𱠕𘡹𑜸𢴛𤫡ϛ𱪽𐳙𦾆𢰫𭏉𫥻𬒊儲Ẃ"]

The API also supports restricting characters to one or more Unicode blocks:

Character.UnicodeBlock[] blocks = {
    Character.UnicodeBlock.EMOTICONS,
    Character.UnicodeBlock.CYRILLIC
};

Comment comment = Instancio.of(Comment.class)
    .generate(field(Comment::getText), gen -> gen.string().length(10).unicode(blocks))
    .create();

// Sample output:
// Comment[text="ф😬😅😟фҖӝ😲ЭӍ"]

In addition, Unicode strings can be generated using the Gen class:

String unicodeString = Gen.string().unicode().length(50).get();

New setting Keys.STRING_TYPE

The new setting allows customising generated string types via Settings:

Comment comment = Instancio.of(Comment.class)
    .withSetting(Keys.STRING_TYPE, StringType.ALPHANUMERIC)
    .create();

or globally using instancio.properties:

string.type=ALPHANUMERIC

Support for generating numeric sequence strings

Numeric sequence strings can be generated using the numericSequence() spec method or Keys.STRING_TYPE setting:

record Phone(String countryCode, String number) {}

List<Phone> phones = Instancio.ofList(Phone.class)
    .withSetting(Keys.STRING_TYPE, StringType.NUMERIC_SEQUENCE)
    .create();

// Sample output:
// [Phone[countryCode=1,number=2],
//  Phone[countryCode=3,number=4],
//  Phone[countryCode=5,number=6]]

This setting can be combined with Keys.STRING_FIELD_PREFIX_ENABLED to produce sequential strings that are prefixed with field name:

List<Phone> phones = Instancio.ofList(Phone.class)
    .withSetting(Keys.STRING_FIELD_PREFIX_ENABLED, true)
    .withSetting(Keys.STRING_TYPE, StringType.NUMERIC_SEQUENCE)
    .create();

// Sample output:
// [Phone[countryCode=countryCode_1,number=number_2],
//  Phone[countryCode=countryCode_3,number=number_4],
//  Phone[countryCode=countryCode_5,number=number_6]]

  • Perf: minor string generator improvement by @armandino in #1017
  • String generator spec unicode() method + StringType setting by @armandino in #1018
  • New setting StringType.NUMERIC_SEQUENCE for generating sequential strings by @armandino in #1019
  • Add numericSequence() to string generator spec by @armandino in #1020
  • Minor refactoring: extract selector base class by @armandino in #1022
  • New top-level APIs for creating blank objects by @armandino in #1021
  • If a primitive target is set to null, set the value to the primitive's default by @armandino in #1027
  • Renamed withBlank() to setBlank() by @armandino in #1028
  • Bump version.kotlin from 1.9.24 to 2.0.0 by @dependabot in #1023
  • Bump jakarta.validation:jakarta.validation-api from 3.0.2 to 3.1.0 by @dependabot in #1025
  • Bump jakarta.persistence:jakarta.persistence-api from 3.0.0 to 3.2.0 by @dependabot in #1024
  • Revert "Bump jakarta.persistence:jakarta.persistence-api from 3.0.0 to 3.2.0" by @armandino in #1029
  • Bug fix: collection/map spec with subtype throws exception from GeneratorProvider SPI by @armandino in #1030

Full Changelog: instancio-parent-4.6.0...instancio-parent-4.7.0

4.6.0

12 May 22:46
Compare
Choose a tag to compare

What's Changed

New Features

New top-level API filter()

Thefilter() method can be used to filter generated values using a predicate. If the predicate evaluates to false for a given value, a new value will be generated. The new value will also be tested against the predicate, and so on.

Example 1: generate a list of even numbers
List<Integer> evenNumbers = Instancio.ofList(Integer.class)
    .filter(allInts(), (Integer i) -> i % 2 == 0)
    .create();
Example 2: generate a list of objects with unique string and numeric values
Set<?> generatedValues = new HashSet<>();

List<Person> persons = Instancio.ofList(Person.class)
    .size(100)
    .filter(all(allInts(), allLongs(), allStrings()), generatedValues::add)
    .create();

Suport for temporal generator spec min() and max()

LocalDate maxDate = LocalDate.now().minusYears(18);

Person adult = Instancio.of(Person.class)
    .generate(field(Person::getDateOfBirth), gen -> gen.temporal().localDate().max(maxDate))
    .create();

// Sample output:
// Person[dateOfBirth=1984-01-26]

  • Bump org.apache.maven.plugins:maven-jar-plugin from 3.4.0 to 3.4.1 by @dependabot in #996
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.3 to 3.2.4 by @dependabot in #997
  • Bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.20.0 to 0.21.0 by @dependabot in #998
  • Bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.21.0 to 0.21.1 by @dependabot in #999
  • Bump com.puppycrawl.tools:checkstyle from 10.15.0 to 10.16.0 by @dependabot in #1002
  • Bump org.apache.maven.plugins:maven-deploy-plugin from 3.1.1 to 3.1.2 by @dependabot in #1003
  • Suport for temporal generator spec min() and max() by @armandino in #1010
  • Bump version.jooq from 3.19.7 to 3.19.8 by @dependabot in #1009
  • Bump com.github.spotbugs:spotbugs-maven-plugin from 4.8.4.0 to 4.8.5.0 by @dependabot in #1011
  • Bump version.kotlin from 1.9.23 to 1.9.24 by @dependabot in #1013
  • Bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.21.1 to 0.21.2 by @dependabot in #1012
  • Bug fix: setModel() with primitive selectors by @armandino in #1014
  • New top-level API filter() by @armandino in #1015
  • Bump com.google.guava:guava from 33.1.0-jre to 33.2.0-jre by @dependabot in #1008

Full Changelog: instancio-parent-4.5.1...instancio-parent-4.6.0

4.5.1

18 Apr 04:06
Compare
Choose a tag to compare

What's Changed

  • Bump nl.jqno.equalsverifier:equalsverifier-nodep from 3.15.8 to 3.16 by @dependabot in #978
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.1 to 3.2.2 by @dependabot in #979
  • Bump org.ow2.asm:asm from 9.6 to 9.7 by @dependabot in #977
  • Bump com.puppycrawl.tools:checkstyle from 10.14.2 to 10.15.0 by @dependabot in #981
  • Bump org.jacoco:jacoco-maven-plugin from 0.8.11 to 0.8.12 by @dependabot in #982
  • Bump nl.jqno.equalsverifier:equalsverifier-nodep from 3.16 to 3.16.1 by @dependabot in #983
  • Bump version.jooq from 3.19.6 to 3.19.7 by @dependabot in #985
  • Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1 by @dependabot in #984
  • Bump com.github.spotbugs:spotbugs-maven-plugin from 4.8.3.1 to 4.8.4.0 by @dependabot in #986
  • Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.2 to 3.2.3 by @dependabot in #988
  • Bump com.tngtech.archunit:archunit from 1.2.1 to 1.3.0 by @dependabot in #987
  • Bump org.slf4j:slf4j-api from 2.0.12 to 2.0.13 by @dependabot in #990
  • Bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.0 by @dependabot in #989
  • Add InstancioExtension to feature tests where missing by @armandino in #991
  • Bugfix: generating empty javax.xml.namespace.QName objects leads to NPE by @armandino in #993
  • Fix generator caching by @armandino in #994

Full Changelog: instancio-parent-4.5.0...instancio-parent-4.5.1