Contract maven plugin - incremental test generation (#1361)
* Contract maven plugin - incremental test generation * incremental stubs and stub jar generation
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.contract.maven.verifier;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.plugin.MojoExecution;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.shared.incremental.IncrementalBuildHelper;
|
||||
import org.apache.maven.shared.utils.io.DirectoryScanner;
|
||||
|
||||
final class ChangeDetector {
|
||||
|
||||
private ChangeDetector() {
|
||||
}
|
||||
|
||||
static boolean inputFilesChangeDetected(File contractsDirectory,
|
||||
MojoExecution mojoExecution, MavenSession session)
|
||||
throws MojoExecutionException {
|
||||
|
||||
IncrementalBuildHelper incrementalBuildHelper = new IncrementalBuildHelper(
|
||||
mojoExecution, session);
|
||||
|
||||
DirectoryScanner scanner = incrementalBuildHelper.getDirectoryScanner();
|
||||
scanner.setBasedir(contractsDirectory);
|
||||
scanner.scan();
|
||||
boolean changeDetected = incrementalBuildHelper.inputFileTreeChanged(scanner);
|
||||
if (scanner.getIncludedFiles().length == 0) {
|
||||
// at least one input file must exist to consider changed/unchanged
|
||||
// return true to skip incremental build and make visible no input file at all
|
||||
return true;
|
||||
}
|
||||
return changeDetected;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import java.util.Map;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.model.Dependency;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecution;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugins.annotations.Component;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
@@ -37,6 +38,8 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig
|
||||
import org.springframework.cloud.contract.verifier.converter.RecursiveFilesConverter;
|
||||
import org.springframework.cloud.contract.verifier.converter.ToYamlConverter;
|
||||
|
||||
import static org.springframework.cloud.contract.maven.verifier.ChangeDetector.inputFilesChangeDetected;
|
||||
|
||||
/**
|
||||
* Convert Spring Cloud Contract Verifier contracts into stubs mappings.
|
||||
* <p>
|
||||
@@ -188,6 +191,19 @@ public class ConvertMojo extends AbstractMojo {
|
||||
@Parameter(property = "failOnNoContracts", defaultValue = "true")
|
||||
private boolean failOnNoContracts;
|
||||
|
||||
/**
|
||||
* If set to true then stubs are created only when contracts have changed since last
|
||||
* build.
|
||||
*/
|
||||
@Parameter(property = "incrementalContractStubs", defaultValue = "true")
|
||||
private boolean incrementalContractStubs = true;
|
||||
|
||||
@Parameter(defaultValue = "${mojoExecution}", readonly = true, required = true)
|
||||
private MojoExecution mojoExecution;
|
||||
|
||||
@Parameter(defaultValue = "${session}", readonly = true, required = true)
|
||||
private MavenSession session;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException {
|
||||
if (this.skip) {
|
||||
@@ -205,7 +221,17 @@ public class ConvertMojo extends AbstractMojo {
|
||||
config.setExcludeBuildFolders(this.excludeBuildFolders);
|
||||
File contractsDirectory = locationOfContracts(config);
|
||||
contractsDirectory = contractSubfolderIfPresent(contractsDirectory);
|
||||
|
||||
if (this.incrementalContractStubs && !inputFilesChangeDetected(contractsDirectory,
|
||||
mojoExecution, session)) {
|
||||
getLog().info("Nothing to generate - all stubs are up to date");
|
||||
return;
|
||||
}
|
||||
|
||||
File contractsDslDir = contractsDslDir(contractsDirectory);
|
||||
LeftOverPrevention leftOverPrevention = new LeftOverPrevention(
|
||||
this.stubsDirectory, mojoExecution, session);
|
||||
|
||||
File copiedContracts = copyContracts(rootPath, config, contractsDirectory);
|
||||
if (this.convertToYaml) {
|
||||
contractsDslDir = copiedContracts;
|
||||
@@ -220,6 +246,7 @@ public class ConvertMojo extends AbstractMojo {
|
||||
config.getExcludedFiles(), config.getIncludedContracts(),
|
||||
config.isExcludeBuildFolders());
|
||||
converter.processFiles();
|
||||
leftOverPrevention.deleteLeftOvers();
|
||||
}
|
||||
|
||||
private void convertBackedUpDslsToYaml(String rootPath,
|
||||
|
||||
@@ -21,7 +21,9 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecution;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Component;
|
||||
@@ -33,6 +35,8 @@ import org.apache.maven.project.MavenProjectHelper;
|
||||
import org.codehaus.plexus.archiver.Archiver;
|
||||
import org.codehaus.plexus.archiver.jar.JarArchiver;
|
||||
|
||||
import static org.springframework.cloud.contract.maven.verifier.ChangeDetector.inputFilesChangeDetected;
|
||||
|
||||
/**
|
||||
* Picks the converted .json files and creates a jar. Requires convert to be executed
|
||||
* first.
|
||||
@@ -86,6 +90,19 @@ public class GenerateStubsMojo extends AbstractMojo {
|
||||
@Parameter(defaultValue = "stubs")
|
||||
private String classifier;
|
||||
|
||||
/**
|
||||
* If set to true then stubs jar is created only when stubs have changed since last
|
||||
* build.
|
||||
*/
|
||||
@Parameter(property = "incrementalContractStubsJar", defaultValue = "true")
|
||||
private boolean incrementalContractStubsJar = true;
|
||||
|
||||
@Parameter(defaultValue = "${mojoExecution}", readonly = true, required = true)
|
||||
private MojoExecution mojoExecution;
|
||||
|
||||
@Parameter(defaultValue = "${session}", readonly = true, required = true)
|
||||
private MavenSession session;
|
||||
|
||||
/**
|
||||
* When enabled, this flag will tell stub runner to throw an exception when no stubs /
|
||||
* contracts were found.
|
||||
@@ -111,6 +128,11 @@ public class GenerateStubsMojo extends AbstractMojo {
|
||||
+ this.outputDirectory.getAbsolutePath()
|
||||
+ "] .\nPlease make sure that spring-cloud-contract:convert was invoked");
|
||||
}
|
||||
if (this.incrementalContractStubsJar
|
||||
&& !inputFilesChangeDetected(outputDirectory, mojoExecution, session)) {
|
||||
getLog().info("Nothing to generate - stubs jar is up to date");
|
||||
return;
|
||||
}
|
||||
File stubsJarFile = createStubJar(this.outputDirectory);
|
||||
this.projectHelper.attachArtifact(this.project, "jar", this.classifier,
|
||||
stubsJarFile);
|
||||
|
||||
@@ -21,9 +21,11 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.model.Dependency;
|
||||
import org.apache.maven.model.Resource;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecution;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
@@ -245,6 +247,19 @@ public class GenerateTestsMojo extends AbstractMojo {
|
||||
@Parameter(property = "failOnInProgress", defaultValue = "true")
|
||||
private boolean failOnInProgress = true;
|
||||
|
||||
/**
|
||||
* If set to true then tests are created only when contracts have changed since last
|
||||
* build.
|
||||
*/
|
||||
@Parameter(property = "incrementalContractTests", defaultValue = "true")
|
||||
private boolean incrementalContractTests = true;
|
||||
|
||||
@Parameter(defaultValue = "${mojoExecution}", readonly = true, required = true)
|
||||
private MojoExecution mojoExecution;
|
||||
|
||||
@Parameter(defaultValue = "${session}", readonly = true, required = true)
|
||||
private MavenSession session;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
if (this.skip || this.mavenTestSkip || this.skipTests) {
|
||||
@@ -280,6 +295,13 @@ public class GenerateTestsMojo extends AbstractMojo {
|
||||
this.contractsDirectory);
|
||||
getLog().info(
|
||||
"Directory with contract is present at [" + contractsDirectory + "]");
|
||||
|
||||
if (this.incrementalContractTests && !ChangeDetector
|
||||
.inputFilesChangeDetected(contractsDirectory, mojoExecution, session)) {
|
||||
getLog().info("Nothing to generate - all classes are up to date");
|
||||
return;
|
||||
}
|
||||
|
||||
setupConfig(config, contractsDirectory);
|
||||
this.project
|
||||
.addTestCompileSourceRoot(this.generatedTestSourcesDir.getAbsolutePath());
|
||||
@@ -297,9 +319,12 @@ public class GenerateTestsMojo extends AbstractMojo {
|
||||
+ this.baseClassMappings);
|
||||
}
|
||||
try {
|
||||
LeftOverPrevention leftOverPrevention = new LeftOverPrevention(
|
||||
this.generatedTestSourcesDir, mojoExecution, session);
|
||||
TestGenerator generator = new TestGenerator(config);
|
||||
int generatedClasses = generator.generate();
|
||||
getLog().info("Generated " + generatedClasses + " test classes.");
|
||||
leftOverPrevention.deleteLeftOvers();
|
||||
}
|
||||
catch (ContractVerifierException e) {
|
||||
throw new MojoExecutionException(
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.contract.maven.verifier;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.plugin.MojoExecution;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.shared.incremental.IncrementalBuildHelper;
|
||||
import org.apache.maven.shared.incremental.IncrementalBuildHelperRequest;
|
||||
|
||||
/**
|
||||
* Prevents the following scenario:
|
||||
*
|
||||
* 1. Contract is added
|
||||
*
|
||||
* 2. Derived file is generated
|
||||
*
|
||||
* 3. Contract is deleted
|
||||
*
|
||||
* 4. Derived file still exists
|
||||
*/
|
||||
class LeftOverPrevention {
|
||||
|
||||
private final IncrementalBuildHelper incrementalBuildHelper;
|
||||
|
||||
private final File generatedDirectory;
|
||||
|
||||
LeftOverPrevention(File generatedDirectory, MojoExecution mojoExecution,
|
||||
MavenSession session) throws MojoExecutionException {
|
||||
this.generatedDirectory = generatedDirectory;
|
||||
this.incrementalBuildHelper = new IncrementalBuildHelper(mojoExecution, session);
|
||||
this.incrementalBuildHelper.beforeRebuildExecution(
|
||||
new IncrementalBuildHelperRequest().outputDirectory(generatedDirectory));
|
||||
}
|
||||
|
||||
void deleteLeftOvers() throws MojoExecutionException {
|
||||
if (generatedDirectory.exists()) {
|
||||
incrementalBuildHelper
|
||||
.afterRebuildExecution(new IncrementalBuildHelperRequest()
|
||||
.outputDirectory(generatedDirectory));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user