SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
2.
“JUnit Pioneer is an extension pack for JUnit 5 or,
to be more precise, for the Jupiter engine”
3.
Recap: JUnit Extensions
Provide a way to extend JUnit’s core features
Well-defined extension API and lifecycle
4.
Simple Example
@ParameterizedTest
@RandomIntSource(min = 5, max = 10, count = 50)
void shouldDoSomethingWithRandomInts(int value) {
// test code...
}
Injecting method
parameters into
tests
Example from https://github.com/kiwiproject/kiwi-test/
5.
@RegisterExtension
static final CuratorTestingServerExtension ZK_TEST_SERVER =
new CuratorTestingServerExtension();
Another Example
Start and stop a
ZooKeeper server before
& after tests
Example from https://github.com/kiwiproject/kiwi-test/
6.
Pioneer Extensions
A collection of useful Jupiter extensions
Easy to integrate into your tests
7.
Pioneer Extensions
Cartesian product
Locale & TimeZone
Environment Vars
Range sources
Issue Info
Disabling tests
Report entries
Stdin & Stdout
System props
Vintage tests
Stopwatch!
* as of 2021-03-04
*
8.
System Properties
@SetSystemProperty(key = "user", value = "bob")
@SetSystemProperty(key = "id", value = "42")
class SystemPropertyTest {
@Test
@ClearSystemProperty(key = "user")
void testWithoutUserProperty() { ... }
@Test
@SetSystemProperty(key = "pwd", value = "12345")
void anotherTest() { ... }
}
12.
Having Issues?
public class SystemOutIssueProcessor
implements IssueProcessor {
@Override
public void processTestResults(List<IssueTestSuite> suites) {
// do something with each test suite
}
}
@Test
@Issue("JUPI-1234")
void shouldFix1234() {
// test code for issue JUPI-1234
}
#1 Annotate
#2 Define processor
14.
I need those TPS reports...
class ReportEntriesTest {
@Test
@ReportEntry("I'm Going To Need Those TPS Reports ASAP")
void testWithReportEntry() { ... }
@Test
@ReportEntry(key = "result", value = "success",
when = PublishCondition.ON_SUCCESS)
@ReportEntry(key = "result", value = "failed",
when = ReportEntry.PublishCondition.ON_FAILURE)
void testWithConditionalEntries() { ... }
}
#1 Annotate
15.
public class SimpleTestExecutionListener
implements TestExecutionListener { ... }
#2 Create a JUnit
TestExecutionListener
com.fortitudetec.junit.pioneering.SimpleTestExecutionListener
META-INF/services/org.junit.platform.launcher.TestExecutionListener
#3 Register implementation
16.
Disabling on display name
Selectively disable parameterized tests
Specify substrings and/or regex to match...
...and disable any tests with a matching name
17.
@DisableIfDisplayName(contains = "42")
@ParameterizedTest(name = "Test scenario {0}")
@ValueSource(ints = {1, 24, 42, 84, 168, 420, 4200, 4242, 17640})
void shouldDisableUsingStringContains(int value) {
if (String.valueOf(value).contains("42")) {
fail("Should not have received %s", value);
}
}
Using a substring to specify
disabling condition
matching
against the
generated
test name
20.
@DisableIfDisplayName(matches = ".*[0-9][3|5]")
@ParameterizedTest(name = "Product: FTCH-000-{0}")
@RandomIntSource(min = 0, max = 1_000, count = 500)
void shouldDisableWhenProductCodeEndsWith_X3_Or_X5(int code) {
var codeString = String.valueOf(code);
if (PRODUCT_NUMBER_PATTERN.matcher(codeString).matches()) {
fail("Should not have received %d", code);
}
}
Combine a regex
with randomized test input
@RandomIntSource from https://github.com/kiwiproject/kiwi-test/
21.
Do, or do not, there is no try
class RetryingAnnotationTest {
@RetryingTest(2)
void shouldFail() {
flakyObject.failsFirstTwoTimes();
}
@RetryingTest(3)
void shouldPass() {
flakyObject.failsFirstTwoTimes();
}
}
24.
& Stdout
@Test
@StdIo
void shouldInterceptStandardOutput(StdOut stdOut) {
System.out.println("The answer is 24");
System.out.println("No, the real answer is always 42");
assertThat(stdOut.capturedLines()).containsExactly(
"The answer is 24",
"No, the real answer is always 42"
);
}
25.
How long did that take?
class StopwatchTest {
@RepeatedTest(value = 10)
@Stopwatch
void shouldReportElapsedTime() { ... }
}
Elapsed time will be published
via a TestReporter, so that a
TestExecutionListener can
receive it
26.
Out on the range...
Create ranges of ints, longs, etc. as test input
Use with parameterized tests
Specify lower and upper bounds
Upper bound can be inclusive or exclusive
27.
@ParameterizedTest
@IntRangeSource(from = 0, to = 10)
void shouldGenerateIntegers(int value) {
assertThat(value).isBetween(0, 9);
failIfSeeUpperBound(value, 10);
}
'from' is inclusive;
'to' is exclusive by default
29.
@ParameterizedTest
@LongRangeSource(from = -100_000, to = 100_000, step = 5_000)
void shouldAllowChangingTheStep(long value) {
assertThat(value).isBetween(-100_000L, 95_000L);
failIfSeeUpperBound(value, 100_000);
}
change difference between
generated values using 'step'
30.
@ParameterizedTest
@DoubleRangeSource(from = 0.0, to = 10.0, step = 0.5, closed = true)
void shouldAllowClosedRanges(double value) {
assertThat(value).isBetween(0.0, 10.0);
}
make a closed range
31.
The best vintage?
Pioneer's vintage @Test replaces JUnit 4 @Test...
...but marks the method as a Jupiter test
Supports expected and timeout parameters
33.
Generate cartesian product of all inputs
Use @CartesianProductTest instead of
Jupiter @Test annotations
Pioneer provides custom argument sources
You can also provide a custom @ArgumentsSource
34.
@CartesianProductTest({"0", "1"})
void shouldProduceAllCombinationsOfThree(String x,
String y,
String z) {
List.of(x, y, z).forEach(this::assertIsZeroOrOne);
}
specify a String array
produces all input
combinations
(2 to the 3rd
power in this
example)
35.
@CartesianProductTest
@CartesianValueSource(strings = {"A", "B", "C"})
@CartesianValueSource(ints = {1, 2, 3})
@CartesianEnumSource(value = Result.class,
names = {"SKIPPED"},
mode = CartesianEnumSource.Mode.EXCLUDE)
void shouldProduceAllCombinationsForCartesianValueSources(
String x, int y, Result z) {
assertThat(equalsAny(x, "A", "B", "C")).isTrue();
assertThat(Range.closed(1, 3).contains(y)).isTrue();
assertThat(z).isNotNull();
}
Analogous to Jupiter's
@ValueSource and
@EnumSource
36.
Using @CartesianValueSource
and @CartesianEnumSource
37.
Danger Will Robinson!
You must use Pioneer's @CartesianXyxSource
with @CartesianProductTest
Trying to use plain Jupiter sources like
@ValueSource will result in exceptions
38.
@CartesianProductTest
@IntRangeSource(from = 1, to = 4, closed = true)
@LongRangeSource(from = 1000, to = 1005, closed = true)
void shouldWorkWithRangeSources(int x, long y) {
assertThat(Range.closed(1, 4).contains(x)).isTrue();
assertThat(Range.closed(1000L, 1005L).contains(y)).isTrue();
}
Also works with
Pioneer range
sources
39.
Using several of Pioneer's
@XyzRangeSource annotations
with @CartesianProductTest
40.
Can also create custom factory methods
Cartesian Argument Factories
Must be static & return CartesianProductTest.Sets
Use naming convention or factory parameter
in @CartesianProductTest
41.
@CartesianProductTest(factory = "customProduct")
void shouldAllowCustomArgumentFactory(
String greek, Result result, int level) {
assertThat(equalsAny(greek, "Alpha", "Beta", "Gamma")).isTrue();
assertThat(result).isNotNull();
assertThat(Range.closedOpen(0, 5).contains(level)).isTrue();
}
static CartesianProductTest.Sets customProduct() {
return new CartesianProductTest.Sets()
.add("Alpha", "Beta", "Gamma")
.add((Object[]) Result.values())
.addAll(Stream.iterate(0, val -> val + 1).limit(5));
}
Instead, we could name the test
'customProduct' (but, I think using
factory is more understandable)
42.
Using our custom
factory with
@CartesianProductTest
(there are 3 * 3 * 5 = 45 input combos)
43.
Wrap Up
Pioneer has some cool things (fact)
Pioneer has some useful things (fact)
You should probably use them (opinion)
44.
Example Code
https://github.com/sleberknight/junit-pioneering-presentation-code
45.
References
JUnit Pioneer website
https://junit-pioneer.org
On GitHub
https://github.com/junit-pioneer/junit-pioneer
IETF BCP 47
https://tools.ietf.org/html/bcp47
IETF language tag (wikipedia)
https://en.wikipedia.org/wiki/IETF_language_tag
JDK 11 Locale
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Locale.html
Local Helper website
https://lh.2xlibre.net
46.
Photos & Images
An artist's impression of a Pioneer spacecraft on its way to interstellar space
https://commons.wikimedia.org/wiki/File:An_artist%27s_impression_of_a_Pioneer_spacecraft_on_its_way_to_interstellar_space.jpg
One more thing...
https://www.flickr.com/photos/mathoov/4681491052
https://creativecommons.org/licenses/by-nc-nd/2.0/
47.
My Info
sleberknight at
fortitudetec.com
www.fortitudetec.com
@sleberknight
scott.leberknight at
gmail
0 likes
Be the first to like this
Views
Total views
688
On SlideShare
0
From Embeds
0
Number of Embeds
392
You have now unlocked unlimited access to 20M+ documents!
Unlimited Reading
Learn faster and smarter from top experts
Unlimited Downloading
Download to take your learnings offline and on the go
You also get free access to Scribd!
Instant access to millions of ebooks, audiobooks, magazines, podcasts and more.
Read and listen offline with any device.
Free access to premium services like Tuneln, Mubi and more.