I am using OpenApi(3.0) for api definition and the openapi-generator-maven-plugin which generates files for me (api objects + endpoints).
Its however generating a test file in the build folder that I do not want. Its called 'OpenApiGeneratorApplicationTests'. It always blocks my compilation bc in the 'target' (=build) folder I do not have the right Spring Boot setup.
How can I avoid the generation of this test file?
This is my maven config:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>6.0.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/ApiDef.yaml</inputSpec>
<generatorName>spring</generatorName>
<modelPackage>${clientPackage}.model</modelPackage>
<invokerPackage>${clientPackage}.invoker</invokerPackage>
<apiPackage>${clientPackage}.api</apiPackage>
<generateApis>true</generateApis>
<generateApiTests>false</generateApiTests>
<generateModelTests>false</generateModelTests>
<configOptions>
<delegatePattern>true</delegatePattern>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
I've encountered today the same issue. So long story short:
By default the generator maven plugin for Spring will generate the 'invoker' - which by implementation is actually a #SpringBootApplication starter class.
#SpringBootApplication
#ComponentScan(basePackages = {"com.mypackage.invoker", "com.mypackage.api" , "org.openapitools.configuration"})
public class OpenApiGeneratorApplication {
public static void main(String[] args) {
SpringApplication.run(OpenApiGeneratorApplication.class, args);
}
#Bean
public Module jsonNullableModule() {
return new JsonNullableModule();
}
}
and will also generate the associated test class OpenApiGeneratorApplicationTests
#SpringBootTest
class OpenApiGeneratorApplicationTests {
#Test
void contextLoads() {
}
}
The problem here is that the src/test/com/mypackage/invoker/OpenApiGeneratorApplicationTests.java, and actually the whole package under test is marked as source, not as test-source and in my case this will result in compile time errors (since the test-scoped dependencies are not found).
I managed to get around it by configuring the maven plugin with
<configOptions>
<interfaceOnly>true</interfaceOnly>
...
</configOptions>
which will skip the generation of the SpringBootApplication and the associated Tests.
I've also submitted a ticket to the OpenApi Generator project's github for marking the
I know this question is not new. But it seems that there is no definite answer. This answer from 2012 states that if generated sources are placed under target/generated-sources/<tool> they will be compiled. ANTLR 4 maven plugin follows this paradigm. Per documentation, the default value of outputDirectory is: ${project.build.directory}/generated-sources/antlr4.
Now in my case I have a custom tool that generates sources. I've set its output directory to be at ${project.build.directory}/generated-sources/whatever and it didn't work. Regarding the whateverpart, I've tried to use the id of the goal that generates the sources and even tried to hijack antlr4 name. No result though.
When I try this solution that suggests using mojo build-helper-maven-plugin it compiles as expected. But according to maven guide to generating sources it should be working without any helper plugin, shouldn't it? Am I missing something?
Here is the POM (fragment) configuration that I use to generate the sources.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>generate-code</id>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includeProjectDependencies>false</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<executableDependency>
<groupId>com.company.product</groupId>
<artifactId>CodeGenerator</artifactId>
</executableDependency>
<arguments>
<argument>${basedir}/</argument>
<argument>${project.build.directory}/generated-sources/generate-code/</argument>
</arguments>
<mainClass>com.company.codegeneration.CodeGenerator</mainClass>
</configuration>
<dependencies>
<dependency>
<groupId>com.company.product</groupId>
<artifactId>CodeGenerator</artifactId>
<version>1.0-SNAPSHOT</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
Your understanding is just a bit incorrect.
Nothing automatic, plugins generating source code typically handle that by adding their output directory (something like target/generated-sources/ by convention) as source directory to the POM so that it will be included later during the compile phase.
Some less well implemented plugins don't do that for you and you have
to add the directory yourself, for example using the Build Helper
Maven Plugin.
As the other answer noted, most plugins typically add the generated code as new source path.
Ex: See antlr4's Antlr4Mojo.java class. Here, the plugin is adding the generated classes to project source by calling addSourceRoot method in execute method.
// Omitted some code
void addSourceRoot(File outputDir) {
if (generateTestSources) {
project.addTestCompileSourceRoot(outputDir.getPath());
}
else {
project.addCompileSourceRoot(outputDir.getPath());
}
}
// Omitted some code
#Override
public void execute() throws MojoExecutionException, MojoFailureException {
// Omitted code
if(project!=null)
{
// Tell Maven that there are some new source files underneath the output
// directory.
addSourceRoot(this.getOutputDirectory());
}
}
// Omitted some code
So, you can either do this in your custom plugin or use the build-helper-maven-plugin.
Using this maven plugin, I was able to generate my classes and reused them in another schema; which is really great!
Now I find myself with a schema needing two episodes (two different packages generated from schemas). I simply tried to add another arg in XJC, but it didn't work.
Then I changed the order of the two args, and the error targetted the other schema. I then understood that both episodes were OK, but it might not be the way of doing things.
Here is some of my pom:
<execution>
<id>business</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
..
<extension>true</extension>
<args>
<arg>-b</arg>
<arg>${project.basedir}/target/episodes/x.episode</arg>
<arg>${project.basedir}/target/episodes/y.episode</arg>
<arg>${project.basedir}/target/episodes/z.episode</arg>
</args>
..
</configuration>
</execution>
And here is what I get:
org.xml.sax.SAXParseException; systemId: file:/****.episode; lineNumber: 2; columnNumber: 65; s4s-elt-schema-ns: namespace element 'bindings' must be from 'http://ww.w3.org/2001.XMLSchema'.
From what I understand (after swapping their call in ), the three schemas/episodes are good, but I cannot use them both at the same time. Any way to do that?
Newbie here, any help much appreciated :).
Author of the maven-jaxb2-plugin here.
Why do you use args, why not just add your episodes in the configuration?
<episodes>
<episode>
<groupId>com.acme.foo</groupId>
<artifactId>package1</artifactId>
<!-- Version is not required if the artifact is
configured as dependency -->
</episode>
<episode>
<groupId>com.acme.foo</groupId>
<artifactId>package2</artifactId>
<!-- Version is not required if the artifact is
configured as dependency -->
</episode>
</episodes>
The whole idea of episodes is that you can point to the JAR (containing the episode file) and XJC will find out and use the binding from the contained episode. Using arg with -b is not what it was inteded for. :)
Concerning the error you're seeing, I guess the way you configure arg makes XJC think that your second and further episodes are actually schemas. I'd try to put intermediate -b arguments or configure all the episodes you refer to in one arg.
But I still think it is not the right way to use episodes. Compile your episodes as separate JARs/separate Maven modules, use them as dependencies and either configure them as episodes or just turn on the useDependenciesAsEpisodes option.
I have done this before on another project. I think you're using the wrong syntax:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>jaxb-Generic-XSD</id>
<phase>generate-sources</phase>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<enableIntrospection>false</enableIntrospection>
<schemaFiles>Generic.xsd</schemaFiles>
<schemaDirectory>${jaxb.schema.folder}</schemaDirectory>
<packageName>you.package.name.here</packageName>
<outputDirectory>${jaxb.output.folder}</outputDirectory>
<extension>true</extension>
<arguments>-b ${core.episode.file} -b ${containers.episode.file}</arguments>
</configuration>
</execution>
</executions>
</plugin>
Note the: <arguments>-b ${core.episode.file} -b ${containers.episode.file}</arguments> line.
I think you're using the same maven plugin, but if not, then take note of the plugin version groupId, artifactId, and use it instead.
I have a Cucumber-JVM, JUnit, Selenium setup. I initiate the run by running RunSmokeTests.java using JUnit within Eclipse. I have also set up a maven profile to run the tests from command line, and possibly Jenkins in the future.
When the tests are run then some of them may fail sometimes, mainly due to the application taking longer than expected. I would then have to re-run these scenarios. At the moment I run them by manually attaching #rerun tag to the ones that failed and then running RunReruns.java, which is similar to RunSmokeTest.java but with #rerun tag.
With the increasing number of automated tests it is time consuming to tag the tests and start the run and clear the tags. Is there a automated way with Cucumber-JVM to re-run failed tests?
RunSmokeTests.java
package testGlueClasses;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#Cucumber.Options(features = "src/test/java", strict = true, format = {
"html:target/CucumberReport", "json:target/JSON/Cucumber.json",
"FrameworkCore.CustomTestReporter" }, tags = { "#SmokeTest" }, glue = {
"FrameworkCore", "MyApp.Utils", "MyApp.StepDefinitions" })
public class RunSmokeTests {
}
Maven snippet:
<profile>
<id>smoke</id>
<properties>
<include.tests>
**/RunSmokeTests.java
</include.tests>
</properties>
</profile>
I came up with another solution to rerun just failed test using maven & cucumber.
1) Record test failures using a RunNotifier
public class RerunningCucumber extends Cucumber {
private final String className;
#SuppressWarnings("rawtypes")
public RerunningCucumber(Class clazz) throws InitializationError, IOException {
super(clazz);
className = clazz.getSimpleName();
}
#Override
public void run(RunNotifier notifier) {
notifier.addListener(new RunListener(){
public void testFailure(Failure failure) throws Exception {
Throwable error = failure.getException();
if (error instanceof AssertionError){
//Nothing. This is a normal failure. Continue
return;
}
//No! A wild exception has appeared!
//Let's run this test again.
RerunningCucumber.addFile(className);
}
});
super.run(notifier);
}
private static final String filename = "target/rerun.properties";
private static final Set<String> addedClasses = new HashSet<String>();
public static synchronized void addFile(String className) throws IOException{
//First find the file
if (addedClasses.contains(className)){
return;
}
File file = new File(filename);
if (!file.exists()){
//Need to create the file
PrintWriter writer = new PrintWriter(file, "UTF-8");
writer.print("retryclasses=**/"+className+".class");
writer.close();
}
else {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file, true)));
out.print(",**/"+className+".class");
out.close();
}
addedClasses.add(className);
}
}
2) Use custom class as a runner for the cucumber tests.
This will run the tests, and whenever there is a failure, output the failed class to a file. Trick is to keep features short and create a lot of test classes to avoid repeating tests.
#RunWith(RerunningCucumber.class)
#CucumberOptions(features = {"classpath:features/testFeature.feature}, format = {
"html:target/cucumber-html-report/testFeature.html",
"json:target/cucumber-json-report/testFeature.json"},
tags = {"#testFeature"})
public class RunTestFeature {
}
3) Add a Rerun profile to maven.
This does three things: 1) it loads the failed classes into memory, 2) cleans JUST the failed classes properties file, and 3) reruns ONLY the failed tests as loaded from the properties file:
<profile>
<id>retry</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<!-- Associate the read-project-properties goal with the initialize
phase, to read the properties file. -->
<execution>
<phase>pre-clean</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>target/rerun.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.6.1</version>
<configuration>
<filesets>
<fileset>
<directory>target</directory>
<includes>
<include>rerun.properties</include>
</includes>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo>Retrying the following classes: "${retryclasses}"</echo>
</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<includes>
<include>${retryclasses}</include>
</includes>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
4) Usage
First test run:
mvn clean test
Next test runs:
mvn clean test -Pretry
mvn clean test -Pretry
mvn clean test -Pretry
...
You can repeat as many times as you want until there are no errors.
I don't have an executable example at hand, but you can do this also on the jvm. There is a RerunFormatter that writes a text file listing the file and line numbers of failed scenarios:
#CucumberOptions(format = {"rerun:target/rerun.txt"})
You should be able to specify this file as input for another test class by prefixing it with #:
#CucumberOptions(features = {"#target/rerun.txt"})
You can pass cucumber options to mvn as below
mvn clean verify -Dcucumber.options="#rerun.txt"
Note there is a tricky part here. If you are using the same test runner for both first run and rerun (and I believe that's what you want), then the test runner would contains something like
#CucumberOptions(plugin = { "rerun:target/rerun.txt"})
If you fire your rerun with maven using the same rerun file name as below
mvn clean verify -Dcucumber.options="#target/rerun.txt"
then cucumber will complain it could not find the rerun file. Why? Because the plugin "rerun:target/rerun.txt" will delete the file first with this test runner.
Workaround is copy/rename the file first, then kick off the mvn run like
mv target/rerun.txt rerun.txt && mvn clean verify -Dcucumber.options="#rerun.txt"
And this is actually what you want. Because say if there are 5 failed scenarios in file target/rerun.txt. And with the rerun after some fix, 2 of them passed. Now the target/rerun.txt will contain the remaining 3 failed scenarios only, which would be your new start point along the debugging way.
For cucumber + java on maven i found this command:
mvn clean test -Dsurefire.rerunFailingTestsCount=2
You must have an actual version of surefire plugin, mine is 3.0.0-M5.
And nothing else special u even need.
Found solution here Surefire rerun failing tests not working
1)
With junit4 (cucumber-junit engine) it can be done easily with rerun plugin
and features cucumber option. Add another maven profile for runner for failed scenarios, for example RerunCucumber.class.
Run your initial build with main test runner and pass rerun plugin:
#RunWith(Cucumber.class)
#CucumberOptions(tags = "#wip",
monochrome = true,
plugin = {"html:target/cucumber", "json:target/wip.json", "rerun:target/rerun_wip.txt"})
public class RunCucumber {
}
After build is finished, failed scenarios will be written to target/rerun_wip.txt.
Then failed scenarios can be executed via rerunner:
#RunWith(Cucumber.class)
#CucumberOptions(features = {"#features = {"#target/rerun_wip.txt"}"},
monochrome = true,
plugin = {"html:target/rerun/failed_tests", "json:target/rerun/failed_tests.json"})
public class RerunCucumber {
}
Will be executed tests from target/rerun_wip.txt.
2)
With junit5 (cucumber-junit-platform-engine) there is no such approach (no features cucumber option). More read about rerun failed scenarios with junit5: https://github.com/cucumber/cucumber-jvm/tree/main/junit-platform-engine, in 'Rerunning failed scenarios' section
You can use cucumber-jvm-parallel-plugin contributed code as a workaround until it goes live. Hit commands as shown below.
git clone -b tagwiseOutlinewiseIssueRerun https://github.com/sugatmankar/cucumber-jvm-parallel-plugin.git
mvn clean install.
Now edit you project pom file and use as stated here.
Example for using this plugin is here.
I have a Maven plugin that expects File[] for one of its config parameters (docs: maven-failsafeplugin). How do you configure such parameter in pom.xml? Ideally, I would like to say "include all files in directory X" or "my-test-output/*.xml".
<executions>
<execution>
<configuration>
<summaryFile>path/to/file</summaryFile>
<summaryFile>path/to/file2</summaryFile>
<summaryFile>...</summaryFile>
</configuration>
<execution/>
<execution>
....
<execution/>
</executions>
Look at the usage page for more info and samples
The File[] should be reflected by some collection type element in which you can nest.
For example summaryFiles:
<summaryFiles>
<summaryFile>/topping/*.xml</pizza>
<summaryFile>/topping/special/cheese.xml</pizza>
</summaryFiles>