Maven / Spring boot project - how to skip #SpringBootTest - java

In my project there are many tests marked with #SpringBootTest which I don't regard as unit tests and rather as integration tests. So I would like to run only the unit tests when I execute:
mvn clean install
actually I want to run this command as part of pre-commit git hook but #SpringBootTest makes it longer to finish execution.
Is there a way to exclude the tests marked with #SpringBootTest? May be there is a pattern we can pass to maven that excludes/certain tests. Or may be write a test suite that includes the spring boot tests.
I did google search to achieve the above but don't have much luck.
Is there even a better way?
#Update: Constraint is maven pom file can't be modified.
#Update2: I have a solution that looks promising:
1. Use #Category("IntegrationTests") for #SpringBootTests tests.
2. Create TestSuite with excludeCategory:
#RunWith(CategoryRunner.class)
#ExcludeCategory("IntegrationTests")
public class TestSuite {
}
3. From mvn command line, run only TestSuite.
I am not sure this is the best. Appreciate anyone's better approach.

If you have different kinds of tests, and want to be able to specify which tests to run, you can do that with #Conditionals or with #Profile.
Examples:
#ConditionalOnProperty("test.run.integration") The class will only be loaded by Spring when property test.run.integration is defined and not false.
#Profile("integrationtest") The class will only be loaded by Spring when profile integrationtest is active.

If you're on JUnit 4, use #IfProfileValue annotation on the test class or method.
Example:
#IfProfileValue(name ="spring.profiles.active", value ="IntegrationTests")
If you're on JUnit 5, as you should be by this time, use #EnabledIf or #DisabledIf.
Example:
#DisabledIf(
expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
reason = "Disabled on Mac OS"
)
See the docs for more details.

try either
mvn clean install -DskipTests
or
mvn clean install -Dmaven.test.skip=true
For more options refer to below links
https://mkyong.com/maven/how-to-skip-maven-unit-test/
https://www.baeldung.com/maven-skipping-tests

Related

How to AND JUnit5 tags with Maven

Is there a way to run only the tests with each of the given tags? For example, can we run only the tests with tag1 AND tag2?
We are using Maven 3.6.2 with version 2.22.2 of Surefire and JUnit 5.5.2 to run tests against many application API endpoints. Each test has at least 3 tags specifying test type, application and method type. Some have more.
We are currently running our tests from the command line to give the tester control over each run:
mvn test -Dgroups=app1,fast
The problem we run into is that the above will run all the tests tagged with app1 OR fast. The result is many dozens of tests being run. The tester's goal is to run only the "fast" tests for "app1".
While it is possible to use excludedGroups, this does not help the tester until after the run. Additionally, we are adding tests and tags every day so what worked today may not work tomorrow.
One of our goals is enabling the specification of tags on the command line and not require the tester to edit the POM to run a different combination of tests. We would like to specify our test sets from the command line and not have to touch the POM between runs. Due to the growing list of test combinations, our POM would become too large to manage efficiently.
Is ANDing JUnit5 tags together even possible with Surefire?
In Maven Surefire/Maven Failsafe you can define groups as you already mentioned but you can define it for JUnit Jupiter (aka JUnit 5) as like this:
mvn test -Dgroups="app1&fast"
or
mvn test -Dgroups="app1|fast"
for more details take a look into the documentation.
BTW: I recommend to upgrade to the most recent versions of maven-surefire-plugin or maven-failsafe-plugin.
They way I've done it was setup interfaces. If there are sub groups I just make the interface extend the parent.
For your case it seems like you have app1 tag and some of those tests tagged fast. Create interface for app1 and another for fast that extends app1. In your tests you can add #Category(app1Fast.class)
When you call mvn test -Dgroups=tests.groups.app1Fast it will run just the fast tags. If you run mvn clean test -Dgroups=tests.groups.app1 it will run everything in app1.
Also, you can tell I created a package called groups to add my interfaces in.
Another also, the interface will be empty -
public interface app1 {}
public interface app1Fast extends app1{}
Sounds like you'll have multiple apps -- app1, app2, etc.
public interface app2{}
public interface app2Fast extends app2{}
Probably other ways, but this is simple enough.
call app1 to test everything in app1, or app1Fast for only the fast tests for app1. Same for app2.
Hope that helps.

TestNg test not running with maven build

I have TestNg unit tests which is supposed to run with my maven clean install.
I don't have any test-suite.xmls in my pom to run testes. Expectation is to run all my test files without any configuration with the maven build.
But this is not happening.
My test class goes like this
public class CreateUtilty{
#Test
public void testScope(){
Creationutiltiy.create("myApp");
// remaing code
}
}
What could have I done wrong ?
Running testNG as you are with no configuration, the surefire plugin expects your test classes to end with Test. Try changing your test class name to CreateUtilityTest and it should be picked up.
The documentation for the maven surefile plugin contains useful information to help you get started.
To find out more about how to include/exlude tests based on naming convention read this.
Try execute your class with following syntax
mvn -Dtest=CreateUtilty test

Spring/JUnit - running Unit Tests that aren't really "tests"

This question is more of a best practices approach. The application we have is Spring Boot 1.5.4 and builds using Gradle. I'm in the process of creating nightly builds with Jenkins, and want to make sure all the unit tests pass in the project.
The project has a number of "tests" like this however:
#SpringBootTest(classes = {Application.class})
#RunWith(SpringRunner.class)
public class DatabaseCreationProcessImplTest {
This particular class creates a sample database image for developers to work off of. Granted we could make straight SQL scripts, but a Java process is useful since there's code that also queries for data from outside sources (e.g. Liferay.)
The reason we're using a unit test for this is because developers can easily run it in IntelliJ to load a new database image. However this isn't really a "test", it's using the test runner as a quick way to run a Java process.
I'm working on setting up nightly builds and I don't want this test to be included in the builds. I can do something like the following in the build script:
test {
exclude 'com/mydomain/service/util/impl/DatabaseCreationProcessImplTest.class'
}
However by doing this, if running the unit test individually in the IDE with the Spring test runner, it is unable to find any tests. I thought about passing in a Boolean value in the Jenkins task for doing this, e.g.
test {
systemProperties 'property': 'value'
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
}
// Exclusions go here
if (Boolean.getBoolean('exclude.tests')) {
exclude 'com/mydomain/service/util/impl/DatabaseCreationProcessImplTest.class'
}
}
However this seems like a hack/kludge... any ways looking for some "best practices" approach for handling this. Is JUnit the right way for quickly running Java processes? Are there other alternatives? Is it possible to create a Gradle script which developers can use to invoke common Java (Spring Boot) process as well?
I think you could group your not-really-tests in a test suite with JUnit's #SuiteClasses annotation:
#Suite.SuiteClasses(DatabaseCreationProcessImplTest.class)
public class NotReallyTests {}
And then use a condition that you pass from your Jenkins command line to exclude the not-really-tests suite:
test {
if (project.hasProperty('excludeNotReallyTests')) {
useJunit {
excludeCategories 'fully.qualified.name.of.your.NotReallyTests'
}
}
}
Your Jenkins command line would then be
$ gradle -PexcludeNotReallyTests=true
It's a little less hacky than your solution in that it keeps track of the grouping of tests that are not really tests in the codebase instead of the build.gradle file.
The Testing API for Android provides several annotations that are used to group tests together. Then you can specify which tests to run by giving one of the annotations on the command line. I do not know the details of how to implement this. It is just a suggestion for you to explore on your own, if you are interested.

Spock unit tests in grails for individual test does not work in intellij

I am trying to run individual spock unit tests using intellij idea.
Consider:
// rest of code
def "Test Something"() {
// test code below
}
In above test, when I goto the test body and right context menu, I get two kinds of tests for Test Something. One is the grails test and other is the junit test.
Referring to this question, the accepted answer recommends using the jUnit runner. But using it, the code simply does not compile(probably because certain plugins and other classes are not available).
(I am not sure though as this is the desired behavior because I am just running a single test and not all tests. So wonder why is it compiling all classes ,including plugin classes not required by the test target class.)
Using the grails runner, I check the configuration and here is the screenshot:
So nothing looks wrong with the command there.
But the test on running gives Test framework quit unexpectedly error.
I try running same command from grails console(CMD windows) and it runs without any error message.
But on checking the output html files(in target/test-reports) I see that none of the tests actually ran!
So what is going on here and why are not individual tests running?
PS:
When I run All tests using test-app command, tests run as expected. Only individual (unit)tests are not running.
Part of the price paid for Spock's nice test naming, is that you can't specify an individual test to run anymore.
Here are some articles about it. The first seems pretty on-point:
Run a specific test in a single test class with Spock and Maven
This one isn't about running a single test, but has some relevance and talks about Spock's test-name conversions, plus Peter Niederwieser chimes in with comments:
Can TestNG see my Spock (JUnit) test results?
A workaround for this could be the #IgnoreRest annotation. Simply annotate the test you want to run with #IgnoreRest, and then specify that test class to run, and only the annotated test will run. http://spockframework.github.io/spock/javadoc/1.0/spock/lang/IgnoreRest.html
Try using the grails unit test and add the following in the command line part:
-Dgrails.env=development
This will run the test as we change the running environment to development . Hope this will help to everyone facing such problems.

Maven Surefire: run a single unit test

I know that it's possible to run a specific test class with -Dtest=MyTest. But is it possible to run a specific test within that class?
I.e. if MyTest defines testFoo() and testBar(), is there a way to specify that only testfoo() should be run?
I'm aware that it's trivially easy to do this in an IDE, but I occasionally need to run tests on the command line on another server.
From Running a Single Test Using Maven Surefire Plugin
With version 2.7.3, you can run only n tests in a single Test Class.
NOTE : it's supported for junit 4.x and TestNG.
You must use the following syntax
mvn -Dtest=TestCircle#mytest test
You can use patterns too
mvn -Dtest=TestCircle#test* test
It will be available as of Surefire 2.8, see SUREFIRE-577
Don't think its available. You can work around it by passing some system properties & ignore execution of tests based on the property value. However it does not seem to add a great value add. There is also TestNG which offers additional features.
http://maven.apache.org/plugins/maven-surefire-plugin/examples/testng.html
To execute one Test at a time, run mvn test
mvn -Dtest=MyUnitlTest test
To execute one Test at a time and a specific method from it:
mvn -Dtest=MyUnitTest#method test
where MyUnitTest is the name of your test and #method is the name of your method.
Execute tests with surefire:
mvn surefire:test

Categories

Resources