Allow to write tests in Kotlin

This commit is contained in:
Clément Fournier
2018-08-21 18:47:21 +02:00
parent e3018c3892
commit ce25568664
10 changed files with 735 additions and 89 deletions

View File

@ -39,6 +39,11 @@
</configuration>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>

View File

@ -1,89 +0,0 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Test;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ParserTstUtil;
public class Java11Test {
private static String loadSource(String name) {
try {
return IOUtils.toString(Java10Test.class.getResourceAsStream("jdkversiontests/java11/" + name),
StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test
public void testLocalVariableSyntaxForLambdaParametersWithJava10() {
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("10",
loadSource("LocalVariableSyntaxForLambdaParameters.java"));
List<ASTLambdaExpression> lambdas = compilationUnit.findDescendantsOfType(ASTLambdaExpression.class);
Assert.assertEquals(4, lambdas.size());
// (var x) -> String.valueOf(x);
List<ASTFormalParameter> formalParameters = lambdas.get(0).findDescendantsOfType(ASTFormalParameter.class);
Assert.assertEquals(1, formalParameters.size());
ASTType type = formalParameters.get(0).getFirstChildOfType(ASTType.class);
assertEquals("var", type.getTypeImage());
assertEquals(1, type.jjtGetNumChildren());
ASTReferenceType referenceType = type.getFirstChildOfType(ASTReferenceType.class);
assertNotNull(referenceType);
assertEquals(1, referenceType.jjtGetNumChildren());
ASTClassOrInterfaceType classType = referenceType.getFirstChildOfType(ASTClassOrInterfaceType.class);
assertNotNull(classType);
assertEquals("var", classType.getImage());
// (var x, var y) -> x + y;
formalParameters = lambdas.get(1).findDescendantsOfType(ASTFormalParameter.class);
Assert.assertEquals(2, formalParameters.size());
type = formalParameters.get(0).getFirstChildOfType(ASTType.class);
assertEquals("var", type.getTypeImage());
assertEquals(1, type.jjtGetNumChildren());
referenceType = type.getFirstChildOfType(ASTReferenceType.class);
assertNotNull(referenceType);
assertEquals(1, referenceType.jjtGetNumChildren());
classType = referenceType.getFirstChildOfType(ASTClassOrInterfaceType.class);
assertNotNull(classType);
assertEquals("var", classType.getImage());
type = formalParameters.get(1).getFirstChildOfType(ASTType.class);
assertEquals("var", type.getTypeImage());
assertEquals(1, type.jjtGetNumChildren());
// (@Nonnull var x) -> String.valueOf(x);
formalParameters = lambdas.get(2).findDescendantsOfType(ASTFormalParameter.class);
Assert.assertEquals(1, formalParameters.size());
Node firstChild = formalParameters.get(0).jjtGetChild(0);
Assert.assertTrue(firstChild instanceof ASTAnnotation);
}
@Test
public void testLocalVariableSyntaxForLambdaParametersWithJava11() {
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("11",
loadSource("LocalVariableSyntaxForLambdaParameters.java"));
List<ASTLambdaExpression> lambdas = compilationUnit.findDescendantsOfType(ASTLambdaExpression.class);
Assert.assertEquals(4, lambdas.size());
// (var x) -> String.valueOf(x);
List<ASTFormalParameter> formalParameters = lambdas.get(0).findDescendantsOfType(ASTFormalParameter.class);
Assert.assertEquals(1, formalParameters.size());
Assert.assertNull(formalParameters.get(0).getTypeNode());
Assert.assertTrue(formalParameters.get(0).isTypeInferred());
}
}

View File

@ -0,0 +1,103 @@
import io.kotlintest.should
import io.kotlintest.shouldBe
import net.sourceforge.pmd.lang.ast.test.matchNode
import net.sourceforge.pmd.lang.java.ast.*
import org.junit.Test
class Java11Test {
@Test
fun testLocalVariableSyntaxForLambdaParametersWithJava10() {
val lambdas = listOf(
"(var x) -> String.valueOf(x)",
"(var x, var y) -> x + y",
"(@Nonnull var x) -> String.valueOf(x)"
).map { parseExpression<ASTLambdaExpression>(it, javaVersion = "10") }
// (var x) -> String.valueOf(x)
lambdas[0] should matchNode<ASTLambdaExpression> {
child<ASTFormalParameters> {
child<ASTFormalParameter> {
child<ASTType> {
it.typeImage shouldBe "var"
child<ASTReferenceType> {
child<ASTClassOrInterfaceType> {
it.image shouldBe "var"
}
}
}
child<ASTVariableDeclaratorId> { }
}
}
unspecifiedChild()
}
// (var x, var y) -> x + y
lambdas[1] should matchNode<ASTLambdaExpression> {
child<ASTFormalParameters> {
child<ASTFormalParameter> {
child<ASTType> {
it.typeImage shouldBe "var"
child<ASTReferenceType> {
child<ASTClassOrInterfaceType> {
it.image shouldBe "var"
}
}
}
child<ASTVariableDeclaratorId> { }
}
child<ASTFormalParameter> {
child<ASTType> {
it.typeImage shouldBe "var"
child<ASTReferenceType> {
child<ASTClassOrInterfaceType> {
it.image shouldBe "var"
}
}
}
child<ASTVariableDeclaratorId> { }
}
}
unspecifiedChild()
}
// (@Nonnull var x) -> String.valueOf(x)
lambdas[2] should matchNode<ASTLambdaExpression> {
child<ASTFormalParameters> {
child<ASTFormalParameter> {
child<ASTAnnotation>(ignoreChildren = true) {}
unspecifiedChildren(2)
}
}
unspecifiedChild()
}
}
@Test
fun testLocalVariableSyntaxForLambdaParametersWithJava11() {
val lambda: ASTLambdaExpression = parseExpression("(var x) -> String.valueOf(x)", javaVersion = "11")
lambda should matchNode<ASTLambdaExpression> {
child<ASTFormalParameters> {
child<ASTFormalParameter> {
it.isTypeInferred shouldBe true
child<ASTVariableDeclaratorId> { }
}
}
unspecifiedChild()
}
}
}

View File

@ -0,0 +1,48 @@
package net.sourceforge.pmd.lang.java.ast
import net.sourceforge.pmd.lang.ast.Node
import net.sourceforge.pmd.lang.java.ParserTstUtil
const val defaultJavaVersion = "11"
inline fun <reified N : Node> parseExpression(expr: String, javaVersion: String = defaultJavaVersion): N =
parseAstExpression(expr, javaVersion).getFirstDescendantOfType(N::class.java)
fun parseAstExpression(expr: String, javaVersion: String = defaultJavaVersion): ASTExpression {
val source = """
class Foo {
{
Object o = $expr;
}
}
""".trimIndent()
val acu = ParserTstUtil.parseAndTypeResolveJava(javaVersion, source)
return acu.getFirstDescendantOfType(ASTVariableInitializer::class.java).jjtGetChild(0) as ASTExpression
}
inline fun <reified N : Node> parseStatement(stmt: String, javaVersion: String = defaultJavaVersion): N =
parseStatement(stmt, javaVersion).getFirstChildOfType(N::class.java)
fun parseStatement(statement: String, javaVersion: String = defaultJavaVersion): ASTBlockStatement {
// place the param in a statement parsing context
val source = """
class Foo {
{
$statement
}
}
""".trimIndent()
val root = ParserTstUtil.parseAndTypeResolveJava(javaVersion, source)
return root.getFirstDescendantOfType(ASTBlockStatement::class.java)
}
// also need e.g. parseDeclaration

View File

@ -38,5 +38,68 @@
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>${kotlin.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.kotlintest</groupId>
<artifactId>kotlintest-runner-junit5</artifactId>
<version>3.1.8</version>
<scope>compile</scope>
</dependency>
<!-- Use pmd-java for tests -->
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-java</artifactId>
<version>6.6.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- The kotlin plugin has to run before the java plugin-->
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>kotlin-compile</id>
<goals>
<goal>compile</goal>
</goals>
<phase>process-sources</phase>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,222 @@
package net.sourceforge.pmd.lang.ast.test
import arrow.legacy.disjunctionTry
import io.kotlintest.Matcher
import io.kotlintest.Result
import net.sourceforge.pmd.lang.ast.Node
import kotlin.test.assertFalse
import kotlin.test.assertTrue
/**
* Wraps a node, providing easy access to [it]. Additional matching
* methods are provided to match children.
*
* @property it Wrapped node
* @param <N> Type of the node
*/
class NWrapper<N : Node> private constructor(val it: N, private val childMatchersAreIgnored: Boolean) {
/** Index to which the next child matcher will apply. */
private var nextChildMatcherIdx = 0
private fun shiftChild(num: Int = 1): Node {
checkChildExists(nextChildMatcherIdx)
val ret = it.jjtGetChild(nextChildMatcherIdx)
nextChildMatcherIdx += num
return ret
}
private fun checkChildExists(childIdx: Int) =
assertTrue("Node has fewer children than expected, child #$childIdx doesn't exist") {
childIdx < it.numChildren
}
/**
* Specify that the next [num] children will only be tested for existence,
* but not for type, or anything else.
*/
fun unspecifiedChildren(num: Int) {
shiftChild(num)
// Checks that the last child mentioned exists
checkChildExists(nextChildMatcherIdx - 1)
}
/**
* Specify that the next child will only be tested for existence,
* but not for type, or anything else.
*/
fun unspecifiedChild() = unspecifiedChildren(1)
/**
* Specify that the next child will be tested against the assertions
* defined by the lambda.
*
* This method asserts that the child exists, and that it is of the
* required type [M]. The lambda is then executed on it. Subsequent
* calls to this method at the same tree level will test the next
* children.
*
* @param ignoreChildren If true, calls to [child] in the [nodeSpec] are ignored.
* The number of children of the child is not asserted either.
* @param nodeSpec Sequence of assertions to carry out on the child node
*
* @param M Expected type of the child
*/
inline fun <reified M : Node> child(ignoreChildren: Boolean = false, noinline nodeSpec: NWrapper<M>.() -> Unit) =
childImpl(ignoreChildren, M::class.java, nodeSpec)
@PublishedApi
internal fun <M : Node> childImpl(ignoreChildren: Boolean, childType: Class<M>, nodeSpec: NWrapper<M>.() -> Unit) {
if (!childMatchersAreIgnored) executeWrapper(childType, shiftChild(), ignoreChildren, nodeSpec)
}
override fun toString(): String {
return "NWrapper<${it.xPathNodeName}>"
}
companion object {
internal val Node.numChildren: Int
get() = this.jjtGetNumChildren()
private val <M : Node> Class<M>.nodeName
get() =
if (simpleName.startsWith("AST", ignoreCase = false))
simpleName.substring("AST".length)
else simpleName
/**
* Execute wrapper assertions on a node.
*
* @param childType Expected type of [toWrap]
* @param toWrap Node on which to execute the assertions
* @param ignoreChildrenMatchers Ignore the children matchers in [spec]
* @param spec Assertions to carry out on [toWrap]
*
* @throws AssertionError If some assertions fail
*/
@PublishedApi
internal fun <M : Node> executeWrapper(childType: Class<M>, toWrap: Node, ignoreChildrenMatchers: Boolean, spec: NWrapper<M>.() -> Unit) {
assertTrue("Expected node to have type ${childType.nodeName}, actual ${toWrap.javaClass.nodeName}") {
childType.isInstance(toWrap)
}
@Suppress("UNCHECKED_CAST")
val wrapper = NWrapper(toWrap as M, ignoreChildrenMatchers)
wrapper.spec()
assertFalse("<${childType.nodeName}>: Wrong number of children, expected ${wrapper.nextChildMatcherIdx}, actual ${wrapper.it.numChildren}") {
!ignoreChildrenMatchers && wrapper.nextChildMatcherIdx != wrapper.it.numChildren
}
}
}
}
/**
* Matcher for a node, using [NWrapper] to specify a subtree against which
* the tested node will be tested.
*
* Use it with [io.kotlintest.should], e.g. `nodeshould matchNode<ASTExpression> {}`.
*
* @param N Expected type of the node
*
* @param ignoreChildren If true, calls to [NWrapper.child] in the [nodeSpec] are ignored.
* The number of children of the child is not asserted either.
*
* @param nodeSpec Sequence of assertions to carry out on the node, which can be referred to by [NWrapper.it].
* Assertions may onsist of [NWrapper.child] calls, which perform the same type of node
* matching on a child of the tested node.
*
* @return A matcher for AST nodes, suitable for use by [io.kotlintest.should].
*
* ### Samples
*
* node should matchNode<ASTStatement> {
*
* // nesting matchers allow to specify a whole subtree
* child<ASTForStatement> {
*
* // This would fail if the first child of the ForStatement wasn't a ForInit
* child<ASTForInit> {
* child<ASTLocalVariableDeclaration> {
*
* // If the parameter ignoreChildren is set to true, the number of children is not asserted
* // Calls to "child" in the block are completely ignored
* // The only checks carried out here are the type test and the assertions of the block
* child<ASTType>(ignoreChildren = true) {
*
* // In a "child" block, the tested node can be referred to as "it"
* // Here, its static type is ASTType, so we can inspect properties
* // of the node and make assertions
*
* it.typeImage shouldBe "int"
* it.type shouldNotBe null
* }
*
* // We don't care about that node, we only care that there is "some" node
* unspecifiedChild()
* }
* }
*
* // The subtree is ignored, but we check a ForUpdate is present at this child position
* child<ASTForUpdate>(ignoreChildren = true) {}
*
* // Here, ignoreChildren is not specified and takes its default value of false.
* // The lambda has no "child" calls and the node will be asserted to have no children
* child<ASTBlock> {}
* }
* }
*/
inline fun <reified N : Node> matchNode(ignoreChildren: Boolean = false, noinline nodeSpec: NWrapper<N>.() -> Unit) = object : Matcher<Node> {
override fun test(value: Node): Result {
val matchRes = disjunctionTry {
NWrapper.executeWrapper(N::class.java, value, ignoreChildren, nodeSpec)
}
val didMatch = matchRes.isRight()
// Output when the node should have matched and did not
//
val failureMessage: String = matchRes.fold({
// Here the node failed
it.message ?: "The node did not match the pattern (no cause specified)"
}, {
// The node matched, which was expected
"SHOULD NOT BE OUTPUT"
})
val negatedMessage = matchRes.fold({
// the node didn't match, which was expected
"SHOULD NOT BE OUTPUT"
}, {
"The node should not have matched this pattern"
})
return Result(didMatch, failureMessage, negatedMessage)
}
}
// This one preserves the stack trace
// It's still hard to read because of the inlines, and possibly only IntelliJ knows how to do that
// I'll try to get kotlintest to preserve the original stack trace
//inline fun <reified M : Node> Node.shouldMatchNode(ignoreChildren: Boolean = false, noinline nodeSpec: NWrapper<M>.() -> Unit) {
// NWrapper.executeWrapper(M::class.java, this, ignoreChildren, nodeSpec)
//}

View File

@ -0,0 +1,107 @@
package net.sourceforge.pmd.lang.ast.test
import io.kotlintest.should
import io.kotlintest.shouldBe
import io.kotlintest.specs.FunSpec
import net.sourceforge.pmd.lang.java.ast.*
class DslTest : FunSpec({
failureTest("Empty matcher spec should check the number of children",
messageContains = setOf("Wrong", "number", "children", "expected 0", "actual 2")) {
parseStatement("int i = 0;") should matchNode<ASTLocalVariableDeclaration> {}
}
test("Matcher with ignoreChildren should not check the number of children") {
parseStatement("int i = 0;") should matchNode<ASTLocalVariableDeclaration>(ignoreChildren = true) {}
}
failureTest("Incorrect node type should cause failure",
messageContains = setOf("Expression", "actual LocalVariableDeclaration")) {
parseStatement("int i = 0;") should matchNode<ASTExpression>(ignoreChildren = true) {}
}
failureTest("Specifying any child in a pattern should cause the number of children to be checked",
messageContains = setOf("number", "children", "expected 1", "actual 2")) {
parseStatement("int i = 0;") should matchNode<ASTLocalVariableDeclaration> {
child<ASTType>(ignoreChildren = true) {}
// There's a VarDeclarator
}
}
test("Unspecified children should shift the next child matchers") {
parseStatement("int i = 0;") should matchNode<ASTLocalVariableDeclaration> {
unspecifiedChild()
child<ASTVariableDeclarator>(ignoreChildren = true) {}
}
}
test("Unspecified children should count in total number of children") {
parseStatement("int i = 0;") should matchNode<ASTLocalVariableDeclaration> {
unspecifiedChildren(2)
}
}
failureTest("Unspecified children should be counted in the number of expected children",
messageContains = setOf("#2 doesn't exist")) {
parseStatement("int i = 0;") should matchNode<ASTLocalVariableDeclaration> {
unspecifiedChildren(3)
}
}
failureTest("Assertions are always executed in order",
messageContains = setOf("PrimitiveType")) {
parseStatement("int[] i = 0;") should matchNode<ASTLocalVariableDeclaration> {
child<ASTType> {
// Here we check that the child type check fails before the assertion
child<ASTPrimitiveType> {}
it.typeImage shouldBe "bratwurst"
}
unspecifiedChild()
}
}
failureTest("Assertions are always executed in order #2",
messageContains = setOf("bratwurst")) {
parseStatement("int[] i = 0;") should matchNode<ASTLocalVariableDeclaration> {
child<ASTType> {
it.typeImage shouldBe "bratwurst"
child<ASTPrimitiveType> {}
}
unspecifiedChild()
}
}
failureTest("Leaf nodes should assert that they have no children",
messageContains = setOf("number", "children", "expected 0")) {
parseStatement("int[] i = 0;") should matchNode<ASTLocalVariableDeclaration> {
child<ASTType> {} // This should fail
unspecifiedChild()
}
}
})

View File

@ -0,0 +1,41 @@
package net.sourceforge.pmd.lang.ast.test
import net.sourceforge.pmd.lang.LanguageRegistry
import net.sourceforge.pmd.lang.ast.Node
import net.sourceforge.pmd.lang.java.JavaLanguageModule
import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit
import java.io.StringReader
// These could be used directly by the pmd-java test module
fun parseStatement(statement: String): Node {
// place the param in a statement parsing context
val source = """
class Foo {
{
$statement
}
}
""".trimIndent()
val root = parseCompilationUnit(source)
return root.getFirstDescendantOfType(ASTBlockStatement::class.java).jjtGetChild(0)
}
fun parseCompilationUnit(sourceCode: String): ASTCompilationUnit {
val languageVersionHandler = LanguageRegistry.getLanguage(JavaLanguageModule.NAME).defaultVersion.languageVersionHandler
val rootNode = languageVersionHandler.getParser(languageVersionHandler.defaultParserOptions).parse(":test:", StringReader(sourceCode))
languageVersionHandler.getQualifiedNameResolutionFacade(ClassLoader.getSystemClassLoader()).start(rootNode)
languageVersionHandler.symbolFacade.start(rootNode)
languageVersionHandler.dataFlowFacade.start(rootNode)
languageVersionHandler.getTypeResolutionFacade(ClassLoader.getSystemClassLoader()).start(rootNode)
languageVersionHandler.multifileFacade.start(rootNode)
return rootNode as ASTCompilationUnit
}

View File

@ -0,0 +1,30 @@
package net.sourceforge.pmd.lang.ast.test
import io.kotlintest.matchers.string.shouldContainIgnoringCase
import io.kotlintest.shouldThrow
import io.kotlintest.specs.AbstractFunSpec
// Improve on the KotlinTest DSL for our specific needs
// a testing DSL testing a testing DSL!
fun AbstractFunSpec.failureTest(testName: String,
messageContains: Set<String> = emptySet(),
param: io.kotlintest.TestContext.() -> kotlin.Unit) {
this.expectFailure<AssertionError>(testName, messageContains, param)
}
inline fun <reified T : Throwable> AbstractFunSpec.expectFailure(testName: String,
messageContains: Set<String> = emptySet(),
noinline param: io.kotlintest.TestContext.() -> kotlin.Unit) {
test(testName) {
val exception = shouldThrow<T> {
this.param() // this is the test context here
}
for (substr in messageContains) exception.message.shouldContainIgnoringCase(substr)
}
}

116
pom.xml
View File

@ -260,6 +260,14 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<maven.compiler.source>1.${java.version}</maven.compiler.source>
<maven.compiler.target>1.${java.version}</maven.compiler.target>
<maven.compiler.test.source>1.8</maven.compiler.test.source>
<maven.compiler.test.target>1.8</maven.compiler.test.target>
<kotlin.compiler.jvmTarget>${maven.compiler.test.target}</kotlin.compiler.jvmTarget>
<kotlin.version>1.2.61</kotlin.version>
<javacc.version>5.0</javacc.version>
<surefire.version>2.22.0</surefire.version>
<checkstyle.version>3.0.0</checkstyle.version>
@ -275,6 +283,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<argLine>-Xmx512m -Dfile.encoding=${project.build.sourceEncoding}</argLine>
<pmd.build-tools.version>1.2</pmd.build-tools.version>
</properties>
<build>
@ -329,6 +338,30 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- Kotlin compiler for test-compile -->
<!-- The kotlin plugin has to run before the java plugin-->
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>kotlin-test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<phase>process-test-sources</phase>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@ -336,6 +369,36 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<configuration>
<release>${java.version}</release>
</configuration>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<source>${maven.compiler.test.source}</source>
<target>${maven.compiler.test.target}</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -369,7 +432,27 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<configuration>
<forkMode>once</forkMode>
<runOrder>alphabetical</runOrder>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
</configuration>
<dependencies>
<!-- Junit 5 = Platform + Jupiter (5) + Vintage (3 & 4)-->
<!-- Junit platform -->
<!-- Needed to use kotlintest -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.2.0</version>
</dependency>
<!-- Junit 3 & 4 engine -->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.3.0-M1</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
@ -853,6 +936,39 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
<artifactId>system-rules</artifactId>
<version>1.8.0</version>
</dependency>
<!-- TEST DEPENDENCIES -->
<!-- Kotlin -->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.kotlintest</groupId>
<artifactId>kotlintest-runner-junit5</artifactId>
<version>3.1.8</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>