I have to exclude my integration tests from their execution by PIT. There is an option excludedTestClasses since version 1.3.0. I tried to pass over these tests by the following configration of the Maven plugin of PIT.
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.3.1</version>
<configuration>
<verbose>true</verbose>
<mutationThreshold>80</mutationThreshold>
<targetClasses>
<param>de.comp.proj.*</param>
</targetClasses>
<excludedTestClasses>
<param>**/*IT.java</param>
</excludedTestClasses>
</configuration>
</plugin>
However PIT is still executing all tests with the suffix IT. I had a look the the source but got lost in the night ;-)
So, how can I skip my integration tests?
PIT filters are matched against the class names in the compiled binary, not against the source file name.
Your filter should look something like
<excludedTestClasses>
<param>de.comp.**.*IT</param>
</excludedTestClasses>
de.comp.*IT excludes all tests in the package de.comp. Using de.comp.**.*IT all tests in subpackages are also ignored.
For those using the Gradle plugin :
pitest {
excludedTestClasses = ['de.comp.**.*IT']
}
I use pitest-maven version 1.4.2.
This config works fine for me:
<excludedTestClasses>
<excludedTestClass>de.com.**.*IT</excludedTestClass>
</excludedTestClasses>
Maybe following syntax was for older versions of pitest-maven:
<excludedTestClasses>
<param>de.comp.**.*IT</param>
</excludedTestClasses>
Related
I have a test project in java, that runs all tests found in the projects listed as dependencies for this project.
#RunWith(ClasspathSuite.class)
#ClassnameFilters({ "com.example.*_Test" })
public class AllRegularTests {
// nothing to do
}
My tests are usually in the test/ folder not in the src/
How can I make the test suite look only for classes in test/, and not in src/ ?
Maybe you can do it with the testSourceDirectory definition but I'm not sure.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testSourceDirectory>${basedir}/src/main/java/</testSourceDirectory>
<testClassesDirectory>${project.build.directory}/classes/</testClassesDirectory>
</configuration>
</plugin>
</plugins>
</build>
Few things seems to be wrong here :
By default Maven uses the following naming conventions when looking for tests to run: Test* *Test *TestCase Your test class doesn't follow these conventions. You should rename it or configure Maven Surefire Plugin to use another pattern for test classes.
unit test code should put under the test folder, it can not be recognized as test class if you put it under the main folder.
eg.
Wrong /my_program/src/main/java/NotTest.java
Right /my_program/src/test/java/MyTest.java
Also, check if your test classes directory (e.g. src/test/java) corresponds to directory listed in property in your pom.xml under property. Took me a while to find that.
I am working on a project to prioritize Junit tests based on their statement coverage for any Maven project (I am picking random projects from Git). So far I am able to get a list of the prioritized tests.
I am not sure how to make the Maven project run the tests in the sequence that I have come up with.
I did some search and found that Maven surefire plugin supports order using the runOrder tag. But the order is fixed - alphabetical/ reverse etc. I also came across TestNG which supports order specified on an XML file.
I cannot modify the source code in the target project( Since the source code is not written by me). I can only add new config files if needed or edit the POM.xml.
How can I achieve this? I would really appreciate if you could please direct me any resource useful to achieve this.
TIA
You can create and use JUnitTestSuite for this.
#RunWith(Suite.class)
#SuiteClasses({Test1.class,
Test2.class
})
public class YourTestSuite {
}
Test suite runs test cases in order in which they are mentioned in #SuiteClasses annotation.
And if you want to run test cases in order through maven goal like maven test goal, you can use this test suite. Just exclude test cases and include test case through plugin configuration given below.
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<excludes>
<exclude>**/*Test.java</exclude>
</excludes>
<includes>
<include>**/*TestSuite.java</include>
</includes>
<additionalClasspathElements>
<additionalClasspathElement>${project.build.sourceDirectory}</additionalClasspathElement>
<additionalClasspathElement>${project.build.testSourceDirectory}</additionalClasspathElement>
</additionalClasspathElements>
<useManifestOnlyJar>false</useManifestOnlyJar>
<forkMode>always</forkMode>
</configuration>
</plugin>
Here is the back ground.
I was working on a project which was using ant build. When we use to create a new Class, we use to write the junit test in same class as ant supported it.The Class Name doesn't have 'Test' naming convention. There are more then 800 Junit tests.
Now we need to move to Maven build structure. Problem is that maven only runs junit where the class name has naming convention 'Test'.
How do i run the junit test which are in in src/main/java/* ?
Also, Is there a way where i can pull all methods that has '#Test' annotations?
Please let me know if you need any further info.
Just because you used to do it like that with Ant, doesn't make it right to keep using it now. Now that you've moved to Maven, you must comply with its way of doing things and follow its conventions. One of them is to keep your production code separate from your tests. A mixture does not make sense, as you are in fact littering your code with useless (for clients of your code) methods. While you can keep doing this and find workarounds, this is not the high-standard route to choose.
What you really need to do as a next step is schedule some refactoring time and carry out the following tasks:
Create src/test/java (and respectively -- src/test/resources).
Create a *Test class for each class that contains #Test annotated methods and place them under src/test/java.
Move those methods to the respective new classes.
Move all your resources that are only used by tests to your src/test/resources directory.
You have to change the configuration of the Surefire plugin, which runs the tests. I have not tested it, but you can try this configuration:
<build>
<testSourceDirectory>src/main/java</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<includes>
<include>**/*.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
I assume since you are using ant, you have a test suite? If so, the easiest way is to change the configuration to use the given test suite:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<includes>
<include>AllTest.class</include>
</includes>
</configuration>
</plugin>
However, I'm not sure if it will look in the src folder too so you may have to move the test suite to the test directory.
As for pulling all methods that have the #Test annotation (I assume without a suite?) you will have to do that yourself if you aren't following the sure-fire test class naming conventions. It isn't too hard to make your own test runner implementation that searches through all your classes in your class path or a sub-folder and finds all classes that meet your criteria and pass that to Junit to run.
If you are using eclipse, you can still execute it as Junit test.
In fact, if your "test classes" didn't put in the test folder, it means that you do not intend to run them as "test" at the maven build action.
Attempting to modify an existing Java/Tomcat app for deployment on Heroku following their tutorial and running into some issues with AppAssembler not finding the entry class. Running target/bin/webapp (or deploying to Heroku) results in Error: Could not find or load main class org.stopbadware.dsp.Main
Executing java -cp target/classes:target/dependency/* org.stopbadware.dsp.Main runs properly however. Here's the relevant portion of pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.1.1</version>
<configuration>
<assembleDirectory>target</assembleDirectory>
<programs>
<program>
<mainClass>org.stopbadware.dsp.Main</mainClass>
<name>webapp</name>
</program>
</programs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
</plugin>
My guess is mvn package is causing AppAssembler to not use the correct classpath, any suggestions?
Your artifact's packaging must be set to jar, otherwise the main class is not found.
<pom>
...
<packaging>jar</packaging>
...
</pom>
The artifact itself is added at the end of the classpath, so nothing other than a JAR file will have any effect.
Try:
mvn clean package jar:jar appassembler:assemble
Was able to solve this by adding "$BASEDIR"/classes to the CLASSPATH line in the generated script. Since the script gets rewritten on each call of mvn package I wrote a short script that calls mvn package and then adds the needed classpath entry.
Obviously a bit of a hack but after a 8+ hours of attempting a more "proper" solution this will have to do for now. Will certainly entertain any more elegant ways of correcting the classpath suggested here.
I was going through that tutorial some time ago and had very similar issue. I came with a bit different approach which works for me very nicely.
First of all, as it was mentioned before, you need to keep your POM's type as jar (<packaging>jar</packaging>) - thanks to that, appassembler plugin will generate a JAR file from your classes and add it to the classpath. So thanks to that your error will go away.
Please note that this tutorial Tomcat is instantiated from application source directory. In many cases that is enough, but please note that using that approach, you will not be able to utilize Servlet #WebServlet annotations as /WEB-INF/classes in sources is empty and Tomcat will not be able to scan your servlet classes. So HelloServlet servlet from that tutorial will not work, unless you add some additional Tomcat initialization (resource configuration) as described here (BTW, you will find more SO questions talking about that resource configuration).
I did a bit different approach:
I run a org.apache.maven.plugins:maven-war-plugin plugin (exploded goal) during package and use that generated directory as my source directory of application. With that approach my web application directory will have /WEB-INF/classes "populated" with classes. That in turn will allow Tomcat to perform scanning job correctly (i.e. Servlet #WebServlet annotations will work).
I also had to change a source of my application in the launcher class:
public static void main(String[] args) throws Exception {
// Web application is generated in directory name as specified in build/finalName
// in maven pom.xml
String webappDirLocation = "target/embeddedTomcatSample/";
Tomcat tomcat = new Tomcat();
// ... remaining code does not change
Changes to POM which I added - included maven-war-plugin just before appassembler plugin:
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
</plugin>
...
Please note that exploded goal is called.
I hope that small change will help you.
One more comment on that tutorial and maven build: note that the tutorial was written to show how simple is to build an application and run it in Heroku. However, that is not the best approach to maven build.
Maven recommendation is that you should adhere to producing one artifact per POM. In your case there are should two artifacts:
Tomcat launcher
Tomcat web application
Both should be build as separate POMs and referenced as modules from your parent POM. If you look at the complexity of that tutorial, it does not make much sense to split that into two modules. But if your applications gets more and more complex (and the launcher gets some additional configurations etc.) it will makes a lot of sense to make that "split". As a matter of fact, there are some "Tomcat launcher" libraries already created so alternatively you could use of one them.
You can set the CLASSPATH_PREFIX environment variable:
export CLASSPATH_PREFIX=target/classes
which will get prepended to the classpath of the generated script.
The first thing is that you are using an old version of appassembler-maven-plugin the current version is 1.3.
What i don't understand why are you defining the
<assembleDirectory>target</assembleDirectory>
folder. There exists a good default value for that. So usually you don't need it. Apart from that you don't need to define an explicit execution which bounds to the package phase, cause the appassembler-maven-plugin is by default bound to the package phase.
Furthermore you can use the useWildcardClassPath configuration option to make your classpath shorter.
<configuration>
<useWildcardClassPath>true</useWildcardClassPath>
<repositoryLayout>flat</repositoryLayout>
...
</configruation>
And that the calling of the generated script shows the error is depending on the thing that the location of the repository where all the dependencies are located in the folder is different than in the generated script defined.
Within our project we declare our SVN tags in the format:
YYYY-MM-DD - v{project.version} [${environment}]
eg 2012-01-16 - v1.0.1 [LIVE]
Is it possible to achieve this with the maven-release plugin (version 2.2.2)?
It worth pointing out that the version and the environment parts are obtained and work with the release plugin. It is purely the timestamp that can't be retrieved.
This is what I would expect would work:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.2.2</version>
<configuration>
<preparationGoals>clean verify</preparationGoals>
<tagNameFormat>${timestamp} - v#{project.version} [${env}]</tagNameFormat>
<checkModificationExcludes>
.
.
.
</checkModificationExcludes>
</configuration>
</plugin>
The timestamp property is generated successfully using the buildnumber-maven-plugin as it is added to the manifest file for inclusion to the war file.
I have tried adding buildnumber:create goal into the preparation goals but it produces the following output when executing the release:prepare
What is SCM release tag or label for "Project Name"? (a.b.c.d) null - v1.0.1 [LIVE]: :
The issue seems to be that the the timestamp property is not generated at the point the tagName is being set which indicates that the preparation goals are not performed at the stage is asks for the tagName.
The following might work (will test it after lunch) although it i'd much rather just call release:prepare
mvn buildnumber:create release:prepare
Any input would be welcomed.
Cheers
EDIT
I have tested using the buildnumber:create release:prepare and it does work as expected although I did have to make further modifications which to be honest is a bit of a pain.
The TagNameFormat currently contains:
YYYY-MM-DD - v{project.version} [${environment}]
This contains spaces and square brackets and upon executing with this format you will get a error indicating the URL is not properly URI encoded. To get round this you must specify the tagNameFormat in a format that is already URI Encoded such as:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.2.2</version>
<configuration>
<preparationGoals>clean verify</preparationGoals>
<tagNameFormat>${timestamp}%20-%20v#{project.version}%20%5B${env}%5D</tagNameFormat>
<checkModificationExcludes>
.
.
.
</checkModificationExcludes>
</configuration>
</plugin>
This is nasty but it does work and it will create the tag as required.
Would be still interested to see if anyone has any suggestions as to how to get the timestamp in the tagNameFormat by just executing:
mvn release:prepare
and not
mvn buildnumber:create release:prepare
As of Maven 2.1 there is a variable: maven.build.timestamp available which can be configured using a property:
<properties>
<maven.build.timestamp.format>yyyyMMdd-HHmm</maven.build.timestamp.format>
</properties>
See: http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Available_Variables
This might make the buildnumber plugin no longer required and should be simpler to use.