diff --git a/jgiven-gradle-plugin/build.gradle b/jgiven-gradle-plugin/build.gradle index c7438733de..b1ae97a076 100644 --- a/jgiven-gradle-plugin/build.gradle +++ b/jgiven-gradle-plugin/build.gradle @@ -1,6 +1,7 @@ plugins { id "java-gradle-plugin" id "com.gradle.plugin-publish" version "0.10.1" + id "groovy" } dependencies { @@ -9,8 +10,9 @@ dependencies { implementation "com.google.guava:guava:$guavaVersion" implementation "com.google.code.gson:gson:$gsonVersion" - testImplementation gradleTestKit() testImplementation project(':jgiven-junit') + testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5' + } gradlePlugin { diff --git a/jgiven-gradle-plugin/src/main/java/com/tngtech/jgiven/gradle/JGivenPlugin.java b/jgiven-gradle-plugin/src/main/java/com/tngtech/jgiven/gradle/JGivenPlugin.java index d3ccbf45c8..981a3905ab 100644 --- a/jgiven-gradle-plugin/src/main/java/com/tngtech/jgiven/gradle/JGivenPlugin.java +++ b/jgiven-gradle-plugin/src/main/java/com/tngtech/jgiven/gradle/JGivenPlugin.java @@ -6,6 +6,7 @@ import org.gradle.api.Action; import org.gradle.api.Plugin; import org.gradle.api.Project; +import org.gradle.api.Task; import org.gradle.api.internal.ConventionMapping; import org.gradle.api.internal.IConventionAware; import org.gradle.api.plugins.ReportingBasePlugin; @@ -18,7 +19,7 @@ public class JGivenPlugin implements Plugin { @Override - public void apply( final Project project ) { + public void apply( final Project project ){ project.getPluginManager().apply( ReportingBasePlugin.class ); addTaskExtension( project ); @@ -26,11 +27,11 @@ public void apply( final Project project ) { configureJGivenReportDefaults( project ); } - private void addTaskExtension( Project project ) { + private void addTaskExtension( Project project ){ project.getTasks().withType( Test.class, this::applyTo ); } - private void applyTo( Test test ) { + private void applyTo( Test test ){ final String testName = test.getName(); final JGivenTaskExtension extension = test.getExtensions().create( "jgiven", JGivenTaskExtension.class ); final Project project = test.getProject(); @@ -42,45 +43,42 @@ private void applyTo( Test test ) { test.getOutputs().dir( resultsDir ).withPropertyName( "jgiven.resultsDir" ); } - test.prependParallelSafeAction( task -> - ( (Test) task ).systemProperty( Config.JGIVEN_REPORT_DIR, extension.getResultsDir().getAbsolutePath() ) ); + // Java lambda classes are created at runtime with a non-deterministic classname. + // Therefore, the class name does not identify the implementation of the lambda and changes between different Gradle runs. + // https://docs.gradle.org/current/userguide/more_about_tasks.html#sec:how_does_it_work + test.prependParallelSafeAction( new Action() { + @Override + public void execute( Task task ){ + ((Test) task).systemProperty( Config.JGIVEN_REPORT_DIR, extension.getResultsDir().getAbsolutePath() ); + } + } ); } - private void configureJGivenReportDefaults( Project project ) { - project.getTasks().withType( JGivenReportTask.class, - reportTask -> reportTask.getReports().all( (Action) report -> { - ConventionMapping mapping = ( (IConventionAware) report ).getConventionMapping(); - mapping.map( "enabled", new Callable() { - @Override - public Boolean call() { - return report.getName().equals( JGivenHtmlReportImpl.NAME ); - } - } ); - } ) ); + private void configureJGivenReportDefaults( Project project ){ + project.getTasks().withType( JGivenReportTask.class, reportTask -> reportTask.getReports().all( (Action) report -> { + ConventionMapping mapping = ( (IConventionAware) report ).getConventionMapping(); + mapping.map( "enabled", (Callable) () -> report.getName().equals( JGivenHtmlReportImpl.NAME ) ); + } ) ); } - private void addDefaultReports( final Project project ) { + private void addDefaultReports( final Project project ){ final ReportingExtension reportingExtension = project.getExtensions().findByType( ReportingExtension.class ); - project.getTasks().withType( Test.class, - test -> { - JGivenReportTask reportTask = project.getTasks() - .create( "jgiven" + WordUtil.capitalize( test.getName() ) + "Report", JGivenReportTask.class ); - configureDefaultReportTask( test, reportTask, reportingExtension ); - } ); + project.getTasks().withType( Test.class, test -> { + final JGivenReportTask reportTask = project.getTasks() + .create( "jgiven" + WordUtil.capitalize( test.getName() ) + "Report", JGivenReportTask.class ); + configureDefaultReportTask( test, reportTask, reportingExtension ); + } ); } private void configureDefaultReportTask( final Test test, JGivenReportTask reportTask, - final ReportingExtension reportingExtension ) { + final ReportingExtension reportingExtension ){ ConventionMapping mapping = ( (IConventionAware) reportTask ).getConventionMapping(); - mapping.map( "results", - (Callable) () -> test.getExtensions().getByType( JGivenTaskExtension.class ).getResultsDir() ); - mapping.getConventionValue( reportTask.getReports(), "reports", false ).all( new Action() { - @Override - public void execute( final Report report ) { - ConventionMapping reportMapping = ( (IConventionAware) report ).getConventionMapping(); - reportMapping.map( "destination", - (Callable) () -> reportingExtension.file( "jgiven" + "/" + test.getName() + "/" + report.getName() ) ); - } - } ); + mapping.map( "results", (Callable) () -> test.getExtensions().getByType( JGivenTaskExtension.class ).getResultsDir() ); + mapping.getConventionValue( reportTask.getReports(), "reports", false ) + .all( (Action) report -> { + ConventionMapping reportMapping = ( (IConventionAware) report ).getConventionMapping(); + reportMapping.map( "destination", + (Callable) () -> reportingExtension.file( "jgiven" + "/" + test.getName() + "/" + report.getName() ) ); + } ); } } diff --git a/jgiven-gradle-plugin/src/test/groovy/com/tngtech.jgiven.gradle/JGivenPluginShould.groovy b/jgiven-gradle-plugin/src/test/groovy/com/tngtech.jgiven.gradle/JGivenPluginShould.groovy new file mode 100644 index 0000000000..6632a2edd8 --- /dev/null +++ b/jgiven-gradle-plugin/src/test/groovy/com/tngtech.jgiven.gradle/JGivenPluginShould.groovy @@ -0,0 +1,67 @@ +package com.tngtech.jgiven.gradle + + +import com.google.common.io.Resources +import org.gradle.testkit.runner.GradleRunner +import org.junit.Rule +import org.junit.rules.TemporaryFolder +import spock.lang.Specification + +import static org.gradle.testkit.runner.TaskOutcome.FROM_CACHE +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class JGivenPluginShould extends Specification { + + @Rule + TemporaryFolder testProjectDir = new TemporaryFolder() + File buildFile + + def setup() { + buildFile = testProjectDir.newFile('build.gradle') + } + + def "test is cacheable"() { + given: + buildFile << """ + plugins { + id 'java' + id 'com.tngtech.jgiven.gradle-plugin' + } + + repositories { jcenter() } + dependencies { + testImplementation 'com.tngtech.jgiven:jgiven-junit:1.0.0-RC4' + testImplementation 'junit:junit:4.12' + } + """ + + testProjectDir.newFolder("src", "test", "java") + File scenario = testProjectDir.newFile("src/test/java/SimpleScenario.java") + scenario << Resources.toByteArray(Resources.getResource("SimpleScenario.java")) + + when: + def result = GradleRunner.create() + .withProjectDir(testProjectDir.getRoot()) + .withArguments("--build-cache", "test", "jgivenTestReport") + .withPluginClasspath() + .build() + + then: + result.task(":test").outcome == SUCCESS + result.task(":jgivenTestReport").outcome == SUCCESS + + when: + new File(testProjectDir.root, 'build').deleteDir() + result = GradleRunner.create() + .withProjectDir(testProjectDir.getRoot()) + .withArguments("--build-cache", "test", "jgivenTestReport") + .withPluginClasspath() + .build() + + + then: + result.task(":test").outcome == FROM_CACHE + result.task(":jgivenTestReport").outcome == FROM_CACHE + + } +} \ No newline at end of file