tl;dr
We show how to develop a regular expression driven by automated tests in JUnit 5. Download setup from github.com/JohannesFKnauf/regex-tdd-parameterized-junit5-example and start playing.
git clone https://github.com/JohannesFKnauf/regex-tdd-parameterized-junit5-example
mvn clean test
Regex Testing: Now for JUnit 5
It’s been a year since the article series about
In the meantime, the popularity of JUnit 5 has grown. It’s time to provide sample code.
Indeed, JUnit 5 will make parameterized tests a first-class citizen. It is a new native feature. However, the JUnit 5 User Guide still marks parameterized tests as experimental .
Providing data by @MethodSource
In order to implement the exact same pattern of 1 self-sufficient simple test class, we choose the @MethodSource
test data source over more complex alternatives. I recommend to read the JUnit 5 User Guide , Nicolai Parlog’s article or Ali Dehghani’s article on Baeldung , if you want to learn more.
@MethodSource
works by reading a Stream
of Arguments
’ from a static method result. The second annotation we need is @ParameterizedTest
, which replaces @Test
on a method.
package de.metamorphant.examples ;
import static org . junit . jupiter . api . Assertions . assertEquals ;
import java.util.stream.Stream ;
import org.junit.jupiter.params.ParameterizedTest ;
import org.junit.jupiter.params.provider.Arguments ;
import org.junit.jupiter.params.provider.MethodSource ;
public class ParameterizedRegexTest {
private static final String REGEX = "[-+]?\\d+(\\.\\d+)?([eE][-+]?\\d+)?" ;
static Stream < Arguments > testCases () {
return Stream . of (
Arguments . of ( "" , false , "empty string" ),
Arguments . of ( "a" , false , "single non-digit" ),
Arguments . of ( "1" , true , "single digit" ),
Arguments . of ( "123" , true , "integer" ),
Arguments . of ( "-123" , true , "integer, negative sign" ),
Arguments . of ( "+123" , true , "integer, positive sign" ),
Arguments . of ( "123.12" , true , "float" ),
Arguments . of ( "123.12e" , false , "float with exponent extension but no value" ),
Arguments . of ( "123.12e12" , true , "float with exponent" ),
Arguments . of ( "123.12E12" , true , "float with uppercase exponent" ),
Arguments . of ( "123.12e12.12" , false , "float with non-integer exponent" ),
Arguments . of ( "123.12e+12" , true , "float with exponent, positive sign" ),
Arguments . of ( "123.12e-12" , true , "float with exponent, negative sign" )
);
}
@ParameterizedTest ( name = "{index} ==> {2}: is {0} well-formed? {1}" )
@MethodSource ( "testCases" )
public void regexTest ( String input , boolean isMatchExpected , String description ) {
Boolean matches = input . matches ( REGEX );
assertEquals ( isMatchExpected , matches );
}
}
That’s all. Pretty simple, isn’t it? It stays ugly Java code, of course.
Build setup
Of course, we still need to set up the proper dependencies.
<project xmlns= "http://maven.apache.org/POM/4.0.0"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion> 4.0.0</modelVersion>
<groupId> de.metamorphant.examples</groupId>
<artifactId> junit5-parameterized-regex-testing-demo</artifactId>
<version> 0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.target> 1.8</maven.compiler.target>
<maven.compiler.source> 1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId> org.junit.jupiter</groupId>
<artifactId> junit-jupiter-api</artifactId>
<version> 5.6.1</version>
<scope> test</scope>
</dependency>
<dependency>
<groupId> org.junit.jupiter</groupId>
<artifactId> junit-jupiter-engine</artifactId>
<version> 5.6.1</version>
<scope> test</scope>
</dependency>
<dependency>
<groupId> org.junit.jupiter</groupId>
<artifactId> junit-jupiter-params</artifactId>
<version> 5.6.1</version>
<scope> test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId> maven-surefire-plugin</artifactId>
<version> 2.22.2</version>
</plugin>
</plugins>
</build>
</project>
A few notes:
org.junit.jupiter:junit-jupiter-params
is the only difference to an ordinary JUnit 5 project. This artifact contains the parameterized test features.
Pinning the surefire plugin to a recent version will already be familiar to you as a JUnit 5 user.
Selecting Java 8 (or above) is needed to use the Arguments.of(...)
static interface methods.
Run and confirm: It’s green.
mvn clean test
Post header background image
by WikimediaImages
from Pixabay .