|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
package example; |
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals; |
|
import static org.junit.jupiter.api.Assertions.assertFalse; |
|
import static org.junit.jupiter.api.Assertions.assertNotEquals; |
|
import static org.junit.jupiter.api.Assertions.assertNotNull; |
|
import static org.junit.jupiter.api.Assertions.assertTrue; |
|
import static org.junit.jupiter.api.Named.named; |
|
import static org.junit.jupiter.params.provider.Arguments.arguments; |
|
import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE; |
|
import static org.junit.jupiter.params.provider.EnumSource.Mode.MATCH_ALL; |
|
|
|
import java.io.File; |
|
import java.lang.annotation.ElementType; |
|
import java.lang.annotation.Retention; |
|
import java.lang.annotation.RetentionPolicy; |
|
import java.lang.annotation.Target; |
|
import java.time.LocalDate; |
|
import java.time.temporal.ChronoUnit; |
|
import java.time.temporal.TemporalUnit; |
|
import java.util.Arrays; |
|
import java.util.EnumSet; |
|
import java.util.List; |
|
import java.util.stream.IntStream; |
|
import java.util.stream.Stream; |
|
|
|
import example.domain.Person; |
|
import example.domain.Person.Gender; |
|
import example.util.StringUtils; |
|
|
|
import org.junit.jupiter.api.AfterEach; |
|
import org.junit.jupiter.api.BeforeEach; |
|
import org.junit.jupiter.api.DisplayName; |
|
import org.junit.jupiter.api.Nested; |
|
import org.junit.jupiter.api.TestInfo; |
|
import org.junit.jupiter.api.TestReporter; |
|
import org.junit.jupiter.api.extension.ExtensionContext; |
|
import org.junit.jupiter.api.extension.ParameterContext; |
|
import org.junit.jupiter.params.ParameterizedTest; |
|
import org.junit.jupiter.params.aggregator.AggregateWith; |
|
import org.junit.jupiter.params.aggregator.ArgumentsAccessor; |
|
import org.junit.jupiter.params.aggregator.ArgumentsAggregator; |
|
import org.junit.jupiter.params.converter.ConvertWith; |
|
import org.junit.jupiter.params.converter.JavaTimeConversionPattern; |
|
import org.junit.jupiter.params.converter.SimpleArgumentConverter; |
|
import org.junit.jupiter.params.converter.TypedArgumentConverter; |
|
import org.junit.jupiter.params.provider.Arguments; |
|
import org.junit.jupiter.params.provider.ArgumentsProvider; |
|
import org.junit.jupiter.params.provider.ArgumentsSource; |
|
import org.junit.jupiter.params.provider.CsvFileSource; |
|
import org.junit.jupiter.params.provider.CsvSource; |
|
import org.junit.jupiter.params.provider.EmptySource; |
|
import org.junit.jupiter.params.provider.EnumSource; |
|
import org.junit.jupiter.params.provider.MethodSource; |
|
import org.junit.jupiter.params.provider.NullAndEmptySource; |
|
import org.junit.jupiter.params.provider.NullSource; |
|
import org.junit.jupiter.params.provider.ValueSource; |
|
|
|
class ParameterizedTestDemo { |
|
|
|
|
|
@ParameterizedTest |
|
@ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" }) |
|
void palindromes(String candidate) { |
|
assertTrue(StringUtils.isPalindrome(candidate)); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@ValueSource(ints = { 1, 2, 3 }) |
|
void testWithValueSource(int argument) { |
|
assertTrue(argument > 0 && argument < 4); |
|
} |
|
|
|
|
|
@Nested |
|
class NullAndEmptySource_1 { |
|
|
|
|
|
@ParameterizedTest |
|
@NullSource |
|
@EmptySource |
|
@ValueSource(strings = { " ", " ", "\t", "\n" }) |
|
void nullEmptyAndBlankStrings(String text) { |
|
assertTrue(text == null || text.trim().isEmpty()); |
|
} |
|
|
|
} |
|
|
|
@Nested |
|
class NullAndEmptySource_2 { |
|
|
|
|
|
@ParameterizedTest |
|
@NullAndEmptySource |
|
@ValueSource(strings = { " ", " ", "\t", "\n" }) |
|
void nullEmptyAndBlankStrings(String text) { |
|
assertTrue(text == null || text.trim().isEmpty()); |
|
} |
|
|
|
} |
|
|
|
|
|
@ParameterizedTest |
|
@EnumSource(ChronoUnit.class) |
|
void testWithEnumSource(TemporalUnit unit) { |
|
assertNotNull(unit); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@EnumSource |
|
void testWithEnumSourceWithAutoDetection(ChronoUnit unit) { |
|
assertNotNull(unit); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@EnumSource(names = { "DAYS", "HOURS" }) |
|
void testWithEnumSourceInclude(ChronoUnit unit) { |
|
assertTrue(EnumSet.of(ChronoUnit.DAYS, ChronoUnit.HOURS).contains(unit)); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@EnumSource(mode = EXCLUDE, names = { "ERAS", "FOREVER" }) |
|
void testWithEnumSourceExclude(ChronoUnit unit) { |
|
assertFalse(EnumSet.of(ChronoUnit.ERAS, ChronoUnit.FOREVER).contains(unit)); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@EnumSource(mode = MATCH_ALL, names = "^.*DAYS$") |
|
void testWithEnumSourceRegex(ChronoUnit unit) { |
|
assertTrue(unit.name().endsWith("DAYS")); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@MethodSource("stringProvider") |
|
void testWithExplicitLocalMethodSource(String argument) { |
|
assertNotNull(argument); |
|
} |
|
|
|
static Stream<String> stringProvider() { |
|
return Stream.of("apple", "banana"); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@MethodSource |
|
void testWithDefaultLocalMethodSource(String argument) { |
|
assertNotNull(argument); |
|
} |
|
|
|
static Stream<String> testWithDefaultLocalMethodSource() { |
|
return Stream.of("apple", "banana"); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@MethodSource("range") |
|
void testWithRangeMethodSource(int argument) { |
|
assertNotEquals(9, argument); |
|
} |
|
|
|
static IntStream range() { |
|
return IntStream.range(0, 20).skip(10); |
|
} |
|
|
|
|
|
|
|
|
|
@ParameterizedTest |
|
@MethodSource("stringIntAndListProvider") |
|
void testWithMultiArgMethodSource(String str, int num, List<String> list) { |
|
assertEquals(5, str.length()); |
|
assertTrue(num >=1 && num <=2); |
|
assertEquals(2, list.size()); |
|
} |
|
|
|
static Stream<Arguments> stringIntAndListProvider() { |
|
return Stream.of( |
|
arguments("apple", 1, Arrays.asList("a", "b")), |
|
arguments("lemon", 2, Arrays.asList("x", "y")) |
|
); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ParameterizedTest |
|
@CsvSource({ |
|
"apple, 1", |
|
"banana, 2", |
|
"'lemon, lime', 0xF1", |
|
"strawberry, 700_000" |
|
}) |
|
void testWithCsvSource(String fruit, int rank) { |
|
assertNotNull(fruit); |
|
assertNotEquals(0, rank); |
|
} |
|
|
|
|
|
|
|
|
|
@ParameterizedTest |
|
@CsvFileSource(resources = "/two-column.csv", numLinesToSkip = 1) |
|
void testWithCsvFileSourceFromClasspath(String country, int reference) { |
|
assertNotNull(country); |
|
assertNotEquals(0, reference); |
|
} |
|
|
|
@ParameterizedTest |
|
@CsvFileSource(files = "src/test/resources/two-column.csv", numLinesToSkip = 1) |
|
void testWithCsvFileSourceFromFile(String country, int reference) { |
|
assertNotNull(country); |
|
assertNotEquals(0, reference); |
|
} |
|
|
|
@ParameterizedTest(name = "[{index}] {arguments}") |
|
@CsvFileSource(resources = "/two-column.csv", useHeadersInDisplayName = true) |
|
void testWithCsvFileSourceAndHeaders(String country, int reference) { |
|
assertNotNull(country); |
|
assertNotEquals(0, reference); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@ArgumentsSource(MyArgumentsProvider.class) |
|
void testWithArgumentsSource(String argument) { |
|
assertNotNull(argument); |
|
} |
|
|
|
|
|
static |
|
|
|
public class MyArgumentsProvider implements ArgumentsProvider { |
|
|
|
@Override |
|
public Stream<? extends Arguments> provideArguments(ExtensionContext context) { |
|
return Stream.of("apple", "banana").map(Arguments::of); |
|
} |
|
} |
|
|
|
|
|
|
|
@BeforeEach |
|
void beforeEach(TestInfo testInfo) { |
|
|
|
} |
|
|
|
@ParameterizedTest |
|
@ValueSource(strings = "apple") |
|
void testWithRegularParameterResolver(String argument, TestReporter testReporter) { |
|
testReporter.publishEntry("argument", argument); |
|
} |
|
|
|
@AfterEach |
|
void afterEach(TestInfo testInfo) { |
|
|
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@ValueSource(strings = "SECONDS") |
|
void testWithImplicitArgumentConversion(ChronoUnit argument) { |
|
assertNotNull(argument.name()); |
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@ValueSource(strings = "42 Cats") |
|
void testWithImplicitFallbackArgumentConversion(Book book) { |
|
assertEquals("42 Cats", book.getTitle()); |
|
} |
|
|
|
|
|
static |
|
|
|
public class Book { |
|
|
|
private final String title; |
|
|
|
private Book(String title) { |
|
this.title = title; |
|
} |
|
|
|
public static Book fromTitle(String title) { |
|
return new Book(title); |
|
} |
|
|
|
public String getTitle() { |
|
return this.title; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
@ParameterizedTest |
|
@EnumSource(ChronoUnit.class) |
|
void testWithExplicitArgumentConversion( |
|
@ConvertWith(ToStringArgumentConverter.class) String argument) { |
|
|
|
assertNotNull(ChronoUnit.valueOf(argument)); |
|
} |
|
|
|
|
|
static |
|
|
|
public class ToStringArgumentConverter extends SimpleArgumentConverter { |
|
|
|
@Override |
|
protected Object convert(Object source, Class<?> targetType) { |
|
assertEquals(String.class, targetType, "Can only convert to String"); |
|
if (source instanceof Enum<?>) { |
|
return ((Enum<?>) source).name(); |
|
} |
|
return String.valueOf(source); |
|
} |
|
} |
|
|
|
|
|
static |
|
|
|
public class ToLengthArgumentConverter extends TypedArgumentConverter<String, Integer> { |
|
|
|
protected ToLengthArgumentConverter() { |
|
super(String.class, Integer.class); |
|
} |
|
|
|
@Override |
|
protected Integer convert(String source) { |
|
return (source != null ? source.length() : 0); |
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
@ValueSource(strings = { "01.01.2017", "31.12.2017" }) |
|
void testWithExplicitJavaTimeConverter( |
|
@JavaTimeConversionPattern("dd.MM.yyyy") LocalDate argument) { |
|
|
|
assertEquals(2017, argument.getYear()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ParameterizedTest |
|
@CsvSource({ |
|
"Jane, Doe, F, 1990-05-20", |
|
"John, Doe, M, 1990-10-22" |
|
}) |
|
void testWithArgumentsAccessor(ArgumentsAccessor arguments) { |
|
Person person = new Person(arguments.getString(0), |
|
arguments.getString(1), |
|
arguments.get(2, Gender.class), |
|
arguments.get(3, LocalDate.class)); |
|
|
|
if (person.getFirstName().equals("Jane")) { |
|
assertEquals(Gender.F, person.getGender()); |
|
} |
|
else { |
|
assertEquals(Gender.M, person.getGender()); |
|
} |
|
assertEquals("Doe", person.getLastName()); |
|
assertEquals(1990, person.getDateOfBirth().getYear()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ParameterizedTest |
|
@CsvSource({ |
|
"Jane, Doe, F, 1990-05-20", |
|
"John, Doe, M, 1990-10-22" |
|
}) |
|
void testWithArgumentsAggregator(@AggregateWith(PersonAggregator.class) Person person) { |
|
|
|
} |
|
|
|
|
|
static |
|
|
|
public class PersonAggregator implements ArgumentsAggregator { |
|
@Override |
|
public Person aggregateArguments(ArgumentsAccessor arguments, ParameterContext context) { |
|
return new Person(arguments.getString(0), |
|
arguments.getString(1), |
|
arguments.get(2, Gender.class), |
|
arguments.get(3, LocalDate.class)); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ParameterizedTest |
|
@CsvSource({ |
|
"Jane, Doe, F, 1990-05-20", |
|
"John, Doe, M, 1990-10-22" |
|
}) |
|
void testWithCustomAggregatorAnnotation(@CsvToPerson Person person) { |
|
|
|
} |
|
|
|
|
|
|
|
@Retention(RetentionPolicy.RUNTIME) |
|
@Target(ElementType.PARAMETER) |
|
@AggregateWith(PersonAggregator.class) |
|
public @interface CsvToPerson { |
|
} |
|
|
|
|
|
|
|
|
|
@DisplayName("Display name of container") |
|
@ParameterizedTest(name = "{index} ==> the rank of ''{0}'' is {1}") |
|
@CsvSource({ "apple, 1", "banana, 2", "'lemon, lime', 3" }) |
|
void testWithCustomDisplayNames(String fruit, int rank) { |
|
} |
|
|
|
|
|
|
|
|
|
@DisplayName("A parameterized test with named arguments") |
|
@ParameterizedTest(name = "{index}: {0}") |
|
@MethodSource("namedArguments") |
|
void testWithNamedArguments(File file) { |
|
} |
|
|
|
static Stream<Arguments> namedArguments() { |
|
return Stream.of( |
|
arguments(named("An important file", new File("path1"))), |
|
arguments(named("Another file", new File("path2"))) |
|
); |
|
} |
|
|
|
|
|
} |
|
|