/*
 * Copyright 2015-2020 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v2.0 which
 * accompanies this distribution and is available at
 *
 * https://www.eclipse.org/legal/epl-v20.html
 */

package org.junit.jupiter.api;

import static java.util.Spliterator.ORDERED;
import static java.util.Spliterators.spliteratorUnknownSize;
import static org.apiguardian.api.API.Status.MAINTAINED;

import java.net.URI;
import java.util.Iterator;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.apiguardian.api.API;
import org.junit.jupiter.api.function.Executable;
import org.junit.jupiter.api.function.ThrowingConsumer;
import org.junit.platform.commons.util.Preconditions;

A DynamicTest is a test case generated at runtime.

It is composed of a display name and an Executable.

Instances of DynamicTest must be generated by factory methods annotated with @TestFactory.

Note that dynamic tests are quite different from standard @Test cases since callbacks such as @BeforeEach and @AfterEach methods are not executed for dynamic tests.

See Also:
Since:5.0
/** * A {@code DynamicTest} is a test case generated at runtime. * * <p>It is composed of a {@linkplain DynamicNode#getDisplayName display name} * and an {@link #getExecutable Executable}. * * <p>Instances of {@code DynamicTest} must be generated by factory methods * annotated with {@link TestFactory @TestFactory}. * * <p>Note that dynamic tests are quite different from standard {@link Test @Test} * cases since callbacks such as {@link BeforeEach @BeforeEach} and * {@link AfterEach @AfterEach} methods are not executed for dynamic tests. * * @since 5.0 * @see #dynamicTest(String, Executable) * @see #stream(Iterator, Function, ThrowingConsumer) * @see Test * @see TestFactory * @see DynamicContainer * @see Executable */
@API(status = MAINTAINED, since = "5.3") public class DynamicTest extends DynamicNode {
Factory for creating a new DynamicTest for the supplied display name and executable code block.
Params:
  • displayName – the display name for the dynamic test; never null or blank
  • executable – the executable code block for the dynamic test; never null
See Also:
/** * Factory for creating a new {@code DynamicTest} for the supplied display * name and executable code block. * * @param displayName the display name for the dynamic test; never * {@code null} or blank * @param executable the executable code block for the dynamic test; * never {@code null} * @see #stream(Iterator, Function, ThrowingConsumer) */
public static DynamicTest dynamicTest(String displayName, Executable executable) { return new DynamicTest(displayName, null, executable); }
Factory for creating a new DynamicTest for the supplied display name, custom test source URI, and executable code block.
Params:
  • displayName – the display name for the dynamic test; never null or blank
  • testSourceUri – a custom test source URI for the dynamic test; may be null if the framework should generate the test source based on the @TestFactory method
  • executable – the executable code block for the dynamic test; never null
See Also:
Since:5.3
/** * Factory for creating a new {@code DynamicTest} for the supplied display * name, custom test source {@link URI}, and executable code block. * * @param displayName the display name for the dynamic test; never * {@code null} or blank * @param testSourceUri a custom test source URI for the dynamic test; may * be {@code null} if the framework should generate the test source based on * the {@code @TestFactory} method * @param executable the executable code block for the dynamic test; * never {@code null} * @since 5.3 * @see #stream(Iterator, Function, ThrowingConsumer) */
public static DynamicTest dynamicTest(String displayName, URI testSourceUri, Executable executable) { return new DynamicTest(displayName, testSourceUri, executable); }
Generate a stream of dynamic tests based on the given generator and test executor.

Use this method when the set of dynamic tests is nondeterministic in nature or when the input comes from an existing Iterator. See stream(Stream<Object>, Function<? super Object,String>, ThrowingConsumer<? super Object>) as an alternative.

The given inputGenerator is responsible for generating input values. A DynamicTest will be added to the resulting stream for each dynamically generated input value, using the given displayNameGenerator and testExecutor.

Params:
  • inputGenerator – an Iterator that serves as a dynamic input generator; never null
  • displayNameGenerator – a function that generates a display name based on an input value; never null
  • testExecutor – a consumer that executes a test based on an input value; never null
Type parameters:
  • <T> – the type of input generated by the inputGenerator and used by the displayNameGenerator and testExecutor
See Also:
Returns:a stream of dynamic tests based on the given generator and executor; never null
/** * Generate a stream of dynamic tests based on the given generator and test * executor. * * <p>Use this method when the set of dynamic tests is nondeterministic in * nature or when the input comes from an existing {@link Iterator}. See * {@link #stream(Stream, Function, ThrowingConsumer)} as an alternative. * * <p>The given {@code inputGenerator} is responsible for generating * input values. A {@link DynamicTest} will be added to the resulting * stream for each dynamically generated input value, using the given * {@code displayNameGenerator} and {@code testExecutor}. * * @param inputGenerator an {@code Iterator} that serves as a dynamic * <em>input generator</em>; never {@code null} * @param displayNameGenerator a function that generates a display name * based on an input value; never {@code null} * @param testExecutor a consumer that executes a test based on an input * value; never {@code null} * @param <T> the type of <em>input</em> generated by the {@code inputGenerator} * and used by the {@code displayNameGenerator} and {@code testExecutor} * @return a stream of dynamic tests based on the given generator and * executor; never {@code null} * @see #dynamicTest(String, Executable) * @see #stream(Stream, Function, ThrowingConsumer) */
public static <T> Stream<DynamicTest> stream(Iterator<T> inputGenerator, Function<? super T, String> displayNameGenerator, ThrowingConsumer<? super T> testExecutor) { Preconditions.notNull(inputGenerator, "inputGenerator must not be null"); return stream(StreamSupport.stream(spliteratorUnknownSize(inputGenerator, ORDERED), false), displayNameGenerator, testExecutor); }
Generate a stream of dynamic tests based on the given input stream and test executor.

Use this method when the set of dynamic tests is nondeterministic in nature or when the input comes from an existing Stream. See stream(Iterator<Object>, Function<? super Object,String>, ThrowingConsumer<? super Object>) as an alternative.

The given inputStream is responsible for supplying input values. A DynamicTest will be added to the resulting stream for each dynamically supplied input value, using the given displayNameGenerator and testExecutor.

Params:
  • inputStream – a Stream that supplies dynamic input values; never null
  • displayNameGenerator – a function that generates a display name based on an input value; never null
  • testExecutor – a consumer that executes a test based on an input value; never null
Type parameters:
  • <T> – the type of input supplied by the inputStream and used by the displayNameGenerator and testExecutor
See Also:
Returns:a stream of dynamic tests based on the given generator and executor; never null
Since:5.7
/** * Generate a stream of dynamic tests based on the given input stream and * test executor. * * <p>Use this method when the set of dynamic tests is nondeterministic in * nature or when the input comes from an existing {@link Stream}. See * {@link #stream(Iterator, Function, ThrowingConsumer)} as an alternative. * * <p>The given {@code inputStream} is responsible for supplying input values. * A {@link DynamicTest} will be added to the resulting stream for each * dynamically supplied input value, using the given {@code displayNameGenerator} * and {@code testExecutor}. * * @param inputStream a {@code Stream} that supplies dynamic input values; * never {@code null} * @param displayNameGenerator a function that generates a display name * based on an input value; never {@code null} * @param testExecutor a consumer that executes a test based on an input * value; never {@code null} * @param <T> the type of <em>input</em> supplied by the {@code inputStream} * and used by the {@code displayNameGenerator} and {@code testExecutor} * @return a stream of dynamic tests based on the given generator and * executor; never {@code null} * @since 5.7 * @see #dynamicTest(String, Executable) * @see #stream(Iterator, Function, ThrowingConsumer) */
@API(status = MAINTAINED, since = "5.7") public static <T> Stream<DynamicTest> stream(Stream<T> inputStream, Function<? super T, String> displayNameGenerator, ThrowingConsumer<? super T> testExecutor) { Preconditions.notNull(inputStream, "inputStream must not be null"); Preconditions.notNull(displayNameGenerator, "displayNameGenerator must not be null"); Preconditions.notNull(testExecutor, "testExecutor must not be null"); return inputStream // .map(input -> dynamicTest(displayNameGenerator.apply(input), () -> testExecutor.accept(input))); } private final Executable executable; private DynamicTest(String displayName, URI testSourceUri, Executable executable) { super(displayName, testSourceUri); this.executable = Preconditions.notNull(executable, "executable must not be null"); }
Get the executable code block associated with this DynamicTest.
/** * Get the {@code executable} code block associated with this {@code DynamicTest}. */
public Executable getExecutable() { return this.executable; } }