Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix JGiven Plugin to be a cacheable task #450

Merged
merged 1 commit into from
Jan 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion jgiven-gradle-plugin/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id "java-gradle-plugin"
id "com.gradle.plugin-publish" version "0.10.1"
id "groovy"
}

dependencies {
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -18,19 +19,19 @@

public class JGivenPlugin implements Plugin<Project> {
@Override
public void apply( final Project project ) {
public void apply( final Project project ){
project.getPluginManager().apply( ReportingBasePlugin.class );

addTaskExtension( project );
addDefaultReports( 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();
Expand All @@ -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<Task>() {
@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>) report -> {
ConventionMapping mapping = ( (IConventionAware) report ).getConventionMapping();
mapping.map( "enabled", new Callable<Boolean>() {
@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>) report -> {
ConventionMapping mapping = ( (IConventionAware) report ).getConventionMapping();
mapping.map( "enabled", (Callable<Boolean>) () -> 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<File>) () -> test.getExtensions().getByType( JGivenTaskExtension.class ).getResultsDir() );
mapping.getConventionValue( reportTask.getReports(), "reports", false ).all( new Action<Report>() {
@Override
public void execute( final Report report ) {
ConventionMapping reportMapping = ( (IConventionAware) report ).getConventionMapping();
reportMapping.map( "destination",
(Callable<File>) () -> reportingExtension.file( "jgiven" + "/" + test.getName() + "/" + report.getName() ) );
}
} );
mapping.map( "results", (Callable<File>) () -> test.getExtensions().getByType( JGivenTaskExtension.class ).getResultsDir() );
mapping.getConventionValue( reportTask.getReports(), "reports", false )
.all( (Action<Report>) report -> {
ConventionMapping reportMapping = ( (IConventionAware) report ).getConventionMapping();
reportMapping.map( "destination",
(Callable<File>) () -> reportingExtension.file( "jgiven" + "/" + test.getName() + "/" + report.getName() ) );
} );
}
}
Original file line number Diff line number Diff line change
@@ -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

}
}