From 35674c8951d8fbe77022478ecfbcc24c31ab126f Mon Sep 17 00:00:00 2001 From: Benjamin DANGLOT Date: Thu, 2 May 2019 21:47:15 +0200 Subject: [PATCH] Feat: junit5 pit (#70) * pom: add dependency to pitest junit 5 * feat: configure the test plugin correctly when running junit5 * test: add a manual test for pit on junit 5 * refactor: remove old commenteed code --- pom.xml | 8 ++- .../stamp_project/testrunner/EntryPoint.java | 67 +++++++++++++------ .../listener/pit/AbstractPitResult.java | 28 ++------ .../testrunner/listener/pit/PitCSVResult.java | 1 - .../testrunner/listener/pit/PitXMLResult.java | 1 - .../testrunner/runner/pit/PitRunner.java | 10 ++- .../testrunner/EntryPointJUnit5Test.java | 25 +++++++ 7 files changed, 92 insertions(+), 48 deletions(-) diff --git a/pom.xml b/pom.xml index b14bddc2..c817a58e 100644 --- a/pom.xml +++ b/pom.xml @@ -130,7 +130,7 @@ org.junit.platform junit-platform-launcher - 1.3.2 + 1.2.0 @@ -161,6 +161,12 @@ 3.0.0 + + org.pitest + pitest-junit5-plugin + 0.8 + + diff --git a/src/main/java/eu/stamp_project/testrunner/EntryPoint.java b/src/main/java/eu/stamp_project/testrunner/EntryPoint.java index cb3f1227..87a48b90 100644 --- a/src/main/java/eu/stamp_project/testrunner/EntryPoint.java +++ b/src/main/java/eu/stamp_project/testrunner/EntryPoint.java @@ -14,7 +14,10 @@ import eu.stamp_project.testrunner.utils.ConstantsHelper; import org.apache.commons.io.FileUtils; import org.jacoco.core.runtime.IRuntime; +import org.junit.jupiter.api.extension.ExtensionContext; import org.objectweb.asm.xml.Processor; +import org.opentest4j.TestAbortedException; +import org.pitest.junit5.JUnit5Configuration; import org.pitest.mutationtest.config.PluginServices; import org.pitest.mutationtest.engine.gregor.GregorMutationEngine; import org.pitest.testapi.TestGroupConfig; @@ -302,7 +305,7 @@ public static Coverage runCoverage(String classpath, String targetProjectClasses EntryPoint.blackList.isEmpty() ? "" : (ParserOptions.FLAG_blackList + ConstantsHelper.WHITE_SPACE + String.join(ConstantsHelper.PATH_SEPARATOR, EntryPoint.blackList)), - }); + }); return EntryPoint.runCoverage(javaCommand); } @@ -376,17 +379,17 @@ public static CoveragePerTestMethod runCoveragePerTestMethods(String classpath, final String javaCommand = String.join(ConstantsHelper.WHITE_SPACE, new String[]{ getJavaCommand(), - classpath + ConstantsHelper.PATH_SEPARATOR + ABSOLUTE_PATH_TO_RUNNER_CLASSES - + ConstantsHelper.PATH_SEPARATOR + ABSOLUTE_PATH_TO_JACOCO_DEPENDENCIES, - EntryPoint.jUnit5Mode ? EntryPoint.JUNIT5_JACOCO_RUNNER_PER_TEST_QUALIFIED_NAME : EntryPoint.JUNIT4_JACOCO_RUNNER_PER_TEST_QUALIFIED_NAME, - ParserOptions.FLAG_pathToCompiledClassesOfTheProject, - targetProjectClasses, ParserOptions.FLAG_fullQualifiedNameOfTestClassToRun, - String.join(ConstantsHelper.PATH_SEPARATOR, fullQualifiedNameOfTestClasses), - methodNames.length == 0 ? "" : ParserOptions.FLAG_testMethodNamesToRun + ConstantsHelper.WHITE_SPACE + - String.join(ConstantsHelper.PATH_SEPARATOR, methodNames), - EntryPoint.blackList.isEmpty() ? "" - : (ParserOptions.FLAG_blackList + ConstantsHelper.WHITE_SPACE - + String.join(ConstantsHelper.PATH_SEPARATOR, EntryPoint.blackList)), + classpath + ConstantsHelper.PATH_SEPARATOR + ABSOLUTE_PATH_TO_RUNNER_CLASSES + + ConstantsHelper.PATH_SEPARATOR + ABSOLUTE_PATH_TO_JACOCO_DEPENDENCIES, + EntryPoint.jUnit5Mode ? EntryPoint.JUNIT5_JACOCO_RUNNER_PER_TEST_QUALIFIED_NAME : EntryPoint.JUNIT4_JACOCO_RUNNER_PER_TEST_QUALIFIED_NAME, + ParserOptions.FLAG_pathToCompiledClassesOfTheProject, + targetProjectClasses, ParserOptions.FLAG_fullQualifiedNameOfTestClassToRun, + String.join(ConstantsHelper.PATH_SEPARATOR, fullQualifiedNameOfTestClasses), + methodNames.length == 0 ? "" : ParserOptions.FLAG_testMethodNamesToRun + ConstantsHelper.WHITE_SPACE + + String.join(ConstantsHelper.PATH_SEPARATOR, methodNames), + EntryPoint.blackList.isEmpty() ? "" + : (ParserOptions.FLAG_blackList + ConstantsHelper.WHITE_SPACE + + String.join(ConstantsHelper.PATH_SEPARATOR, EntryPoint.blackList)), }); try { EntryPoint.runGivenCommandLine(javaCommand); @@ -415,14 +418,26 @@ public static List runPit(final String classpath, final String pathToRootProject, final String filterTargetClasses, final String targetTests) { + final String classpathToExecute; + if (jUnit5Mode) { + classpathToExecute = String.join(ConstantsHelper.PATH_SEPARATOR, + new String[]{ + classpath, + ABSOLUTE_PATH_TO_PIT_DEPENDENCIES, + ABSOLUTE_PATH_TO_PIT_DEPENDENCIES_FOR_JUNIT5 + } + ); + } else { + classpathToExecute = String.join(ConstantsHelper.PATH_SEPARATOR, + new String[]{ + classpath, + ABSOLUTE_PATH_TO_PIT_DEPENDENCIES + } + ); + } PitRunner.main( new String[]{ - String.join(ConstantsHelper.PATH_SEPARATOR, - new String[]{ - classpath, - ABSOLUTE_PATH_TO_PIT_DEPENDENCIES - } - ), + classpathToExecute, pathToRootProject, filterTargetClasses, targetTests, @@ -566,10 +581,9 @@ private static String RemoveWinFileSeparator(String string) { .map(clazz -> clazz.getProtectionDomain().getCodeSource().getLocation()).map(URL::getPath) .map(path -> path.startsWith("file:") ? path.substring("file:".length()) : path) .map(path -> path.split("!")[0]).map(path -> path.replace("/", ConstantsHelper.FILE_SEPARATOR)) - .map(EntryPoint::RemoveWinFileSeparator).map(path -> { - LOGGER.info("{}", path); - return path; - }).collect(Collectors.joining(ConstantsHelper.PATH_SEPARATOR)); + .map(EntryPoint::RemoveWinFileSeparator) + .peek(path -> LOGGER.info("{}", path)) + .collect(Collectors.joining(ConstantsHelper.PATH_SEPARATOR)); private static final List> JACOCO_DEPENDENCIES = Arrays.asList(IRuntime.class, Processor.class, FileUtils.class); @@ -584,9 +598,18 @@ private static String RemoveWinFileSeparator(String string) { DescartesMutationEngine.class ); + private static final List> PIT_DEPENDENCIES_FOR_JUNIT5 = Arrays.asList( + JUnit5Configuration.class, + ExtensionContext.class, + TestAbortedException.class + ); + private static final String ABSOLUTE_PATH_TO_PIT_DEPENDENCIES = CLASSES_TO_PATH_OF_DEPENDENCIES .apply(PIT_DEPENDENCIES); + private static final String ABSOLUTE_PATH_TO_PIT_DEPENDENCIES_FOR_JUNIT5 = CLASSES_TO_PATH_OF_DEPENDENCIES + .apply(PIT_DEPENDENCIES_FOR_JUNIT5); + private static String initAbsolutePathToRunnerClasses() { URL resource = ClassLoader.getSystemClassLoader().getResource("runner-classes/"); diff --git a/src/main/java/eu/stamp_project/testrunner/listener/pit/AbstractPitResult.java b/src/main/java/eu/stamp_project/testrunner/listener/pit/AbstractPitResult.java index 627c864d..c6998d16 100644 --- a/src/main/java/eu/stamp_project/testrunner/listener/pit/AbstractPitResult.java +++ b/src/main/java/eu/stamp_project/testrunner/listener/pit/AbstractPitResult.java @@ -19,8 +19,6 @@ public enum State {SURVIVED, KILLED, NO_COVERAGE, TIMED_OUT, NON_VIABLE, MEMORY_ protected final String simpleNameMethod; -// protected CtMethod testCase = null; - public AbstractPitResult(String fullQualifiedNameOfMutatedClass, AbstractPitResult.State stateOfMutant, String fullQualifiedNameMutantOperator, String fullQualifiedNameMethod, String fullQualifiedNameOfKiller, @@ -56,25 +54,11 @@ public String getFullQualifiedNameOfKiller() { return fullQualifiedNameOfKiller; } - // TODO move this somewhere in DSpot... - /* - public CtMethod getMethod(CtType ctClass) { - if ("none".equals(this.simpleNameMethod)) { - return null; - } else { - if (this.testCase == null) { - List> methodsByName = ctClass.getMethodsByName(this.simpleNameMethod); - if (methodsByName.isEmpty()) { - if (ctClass.getSuperclass() != null) { - return getMethod(ctClass.getSuperclass().getDeclaration()); - } else { - return null; - } - } - this.testCase = methodsByName.get(0); - } - return this.testCase; - } + public String getFullQualifiedNameOfMutatedClass() { + return fullQualifiedNameOfMutatedClass; + } + + public String getSimpleNameMethod() { + return simpleNameMethod; } - */ } diff --git a/src/main/java/eu/stamp_project/testrunner/listener/pit/PitCSVResult.java b/src/main/java/eu/stamp_project/testrunner/listener/pit/PitCSVResult.java index dbdeac03..4f63f2ad 100644 --- a/src/main/java/eu/stamp_project/testrunner/listener/pit/PitCSVResult.java +++ b/src/main/java/eu/stamp_project/testrunner/listener/pit/PitCSVResult.java @@ -52,7 +52,6 @@ public String toString() { ", stateOfMutant=" + stateOfMutant + ", fullQualifiedNameOfKiller='" + fullQualifiedNameOfKiller + '\'' + ", simpleNameMethod='" + simpleNameMethod + '\'' + -// ", testCase=" + testCase + '}'; } } diff --git a/src/main/java/eu/stamp_project/testrunner/listener/pit/PitXMLResult.java b/src/main/java/eu/stamp_project/testrunner/listener/pit/PitXMLResult.java index b5ca9940..6cbce975 100644 --- a/src/main/java/eu/stamp_project/testrunner/listener/pit/PitXMLResult.java +++ b/src/main/java/eu/stamp_project/testrunner/listener/pit/PitXMLResult.java @@ -92,7 +92,6 @@ public String toString() { ", stateOfMutant=" + stateOfMutant + ", fullQualifiedNameOfKiller='" + fullQualifiedNameOfKiller + '\'' + ", simpleNameMethod='" + simpleNameMethod + '\'' + -// ", testCase=" + testCase + '\'' + ", methodDescription='" + methodDescription + '\'' + ", mutationDescription='" + mutationDescription + '\'' + ", index='" + index + '\'' + diff --git a/src/main/java/eu/stamp_project/testrunner/runner/pit/PitRunner.java b/src/main/java/eu/stamp_project/testrunner/runner/pit/PitRunner.java index 33866066..0940d089 100644 --- a/src/main/java/eu/stamp_project/testrunner/runner/pit/PitRunner.java +++ b/src/main/java/eu/stamp_project/testrunner/runner/pit/PitRunner.java @@ -6,7 +6,6 @@ import org.pitest.mutationtest.config.SettingsFactory; import org.pitest.mutationtest.tooling.EntryPoint; import org.pitest.testapi.TestGroupConfig; -import org.pitest.util.Glob; import java.io.File; import java.net.URL; @@ -23,6 +22,10 @@ */ public class PitRunner { + private static final String JUNIT4_TEST_PLUGIN = "junit"; + + private static final String JUNIT5_TEST_PLUGIN = "junit5"; + public final static String REPORT_PITS = "target/report-pits/"; /** @@ -85,6 +88,11 @@ private static ReportOptions createReportOptions(final String classpath, data.setGroupConfig(testGroupConfig); data.setExportLineCoverage(true); data.setMutationEngine(mutationEngine); + data.setTestPlugin( + eu.stamp_project.testrunner.EntryPoint.jUnit5Mode ? + JUNIT5_TEST_PLUGIN : + JUNIT4_TEST_PLUGIN + ); return data; } diff --git a/src/test/java/eu/stamp_project/testrunner/EntryPointJUnit5Test.java b/src/test/java/eu/stamp_project/testrunner/EntryPointJUnit5Test.java index c86b5f8d..5d4d49bf 100644 --- a/src/test/java/eu/stamp_project/testrunner/EntryPointJUnit5Test.java +++ b/src/test/java/eu/stamp_project/testrunner/EntryPointJUnit5Test.java @@ -3,15 +3,19 @@ import eu.stamp_project.testrunner.listener.Coverage; import eu.stamp_project.testrunner.listener.CoveragePerTestMethod; import eu.stamp_project.testrunner.listener.TestResult; +import eu.stamp_project.testrunner.listener.pit.AbstractPitResult; import eu.stamp_project.testrunner.runner.Failure; import eu.stamp_project.testrunner.utils.ConstantsHelper; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import org.junit.jupiter.api.extension.ExtensionContext; import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.util.List; +import java.util.concurrent.TimeoutException; import static org.junit.Assert.*; import static org.junit.Assert.assertEquals; @@ -37,6 +41,27 @@ public void tearDown() throws Exception { EntryPoint.jUnit5Mode = false; } + @Ignore + @Test + public void testPitRun() throws TimeoutException { + + /* + Run pit with default option on test projects. + Default options are using descartes mutation engine and default mutators of descartes. + This result with a list of pit result. + NOTE: it seems that running pit in debug mode (in IDEA) does not work, be careful. + */ + + final List pitResults = EntryPoint.runPit( + JUNIT_CP + ConstantsHelper.PATH_SEPARATOR + TEST_PROJECT_CLASSES, + "src/test/resources/test-projects/", + "example.*", + "junit5.TestSuiteExample" + ); + assertEquals(2, pitResults.size()); + assertEquals(2, pitResults.stream().filter(result -> result.getStateOfMutant() == AbstractPitResult.State.KILLED).count()); + } + @Ignore @Test public void testWithBlackList() throws Exception {