Execute Junit tests using Maven - java

I have 2 classes under src/test/java that I want to run: scen1.class and scen2.class. Both of these have #Test annotated methods.
I have another class called JunitDefinitions.class that has only #Before, #After, #BeforeClass and #AfterClass methods (no #Test).
This is also under src/test/java but under a different package.
Assuming I have the default pom.xml, what should I add to it in order to be able to execute all these 3 classes?

Rename your test classes to Scen1Test.java and Scen2Test.java or include JunitFW.java, Scen1.java and Scen2.java using <includes> configuration, as it's described in the documentation.
The class JunitFW only contains a #Before, so it's not detected as a Test. You have to move the #Before to a class containing #Test or include a #Test in JunitFW class and rename it to JunitFWTest to make it work.
By default, the Surefire Plugin will automatically include all test classes with the following wildcard patterns:
"**/Test*.java" - includes all of its subdirectories and all Java filenames that start with "Test".
"**/*Test.java" - includes all of its subdirectories and all Java filenames that end with "Test".
"**/*Tests.java" - includes all of its subdirectories and all Java filenames that end with "Tests".
"**/*TestCase.java" - includes all of its subdirectories and all Java filenames that end with "TestCase".

Apart from the renaming of your classes as something like Scen1Test.java and Scen2Test.java as suggested by #viniciusartur, which shall help Maven to recognize the test classes to execute them using surefire-plugin.
Another point to note here is that the reason due to which the #Before, #BeforeClass, #After etc are not executed independently without a #Test method is that only
The Test annotation tells JUnit that the public void method to which
it is attached can be run as a test case. To run the method, JUnit
first constructs a fresh instance of the class then invokes the
annotated method.
From the documentation of #Before in JUnit
Annotating a public void method with #Before causes that method to be
run before the Test method. The #Before methods of superclasses will
be run before those of the current class.
So inferring as this, while annotations are processed, if there is no #Test annotation present in the class under /src/test/java(relative to the question based on maven), no further annotations are meaningful to be processed.
Just to note, if you extend this class with another SubClassTest.java consisting of a #Test method, all these methods would be executed then. Since they are processed based on what(#Test) to act on to.

Related

How to order execution of controller test classes in Junit5 / spring boot?

In my entities I have bidirectional one-to-many relation and I would like to write integration tests with mock.mvc. However, before adding parent, I cannot add child. For this reason, I would like to order my test classes like first run AirportControllerTest, secondly RouteControllerTest and lastly FlightController.
Is it possible, or how to handle such case ?
For this specific problem, a hierachical order is better than a sequential order.
If you are using JUnit 5, you can use #Nested tests. https://junit.org/junit5/docs/current/user-guide/#writing-tests-nested
Nest your Test classes in a way that the Parent Test class runs first and the nested Test can use the test objects created by the parent.
Here is a high-level example:
class AirportControllerTest{
#Test
void testAirportController() {
//Add parent here
}
#Nested
class RouteControllerTest {
#Test
void testRouteController() {
//Use test objects from parent here
}
#Nested
class FlightControllerTest{
#Test
void testFlightController() {
//Use test objects from AirportControllerTest & RouteControllerTest
}
}
}
If you are using JUnit 4, you can enclose your Test Classes in a Test Suite. This answer is a good match - https://stackoverflow.com/a/42600619/6352160
Less relevant: For configuring the Test Method order within a Test Class.
If you are using JUnit5, specify #TestMethodOrder in your Test class and use #Order annotation on methods to specify their order of execution. Reference - https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/TestMethodOrder.html.
If using JUnit4, this question has several possible solutions - How to run test methods in specific order in JUnit4?

Set environment variables in Junit5 for each test

I have to migrate tests from JUnit 4 to JUnit 5, I had #Rule which sets EnvironmentVariables variable. In Junit 4 variables were cleared for each test, in JUnit 5 i need the same behaviour, because now running tests are passing separately, but when I ran all tests from class then the second test fails because still has the same environment variables.
I had:
#Rule
public final EnvironmentVariables environmentVariables = new EnvironmentVariables();
#Test
void method1(){...}
#Test
void method2(){...}
I'm not familiar yet with Junit 5 so thanks in advance for any help
What you did with #Rule in JUnit 4 should be done with Extension that provides a very close feature in JUnit 5.
So you could create an Extension for example EnvironmentVariablesExtension that performed the logic of your #Rule and use it in your unit test by annotating your test class(es) #ExtendWith(EnvironmentVariablesExtension.class).
Note that if you use a single #Rule in a single unit test class, you could move this logic into the #BeforeEach lifecyle method that is invoked before each ran test.
If you have just few classes that uses this setup in a single project, you can still introduce an abstract base test class that does this setup in a #BeforeEach method and make your unit test classes inherit from this base class.
One of the greatest value of #Rule is when you want to define multiple rules for an unit test or as you want to reuse rules in other apps/projects. It it is not the case, don't feel constraint to introduce them as Extension in JUnit5 and keep things simple for the moment.
The EnvironmentVariables rule above looks like System Rules - https://github.com/stefanbirkner/system-rules
This was superseded by System Lambda - https://github.com/stefanbirkner/system-lambda which allows a variable to be set inside the body of a test:
withEnvironmentVariable("FOO", "bar")
.execute(() -> { ... test code } );
However, there is a new library called System Stubs - https://github.com/webcompere/system-stubs which contains the equivalent of the OP's code:
#ExtendWith(SystemStubsExtension.class)
class SomeTest {
#SystemStub
private EnvironmentVariables environmentVariables;
#Test
void someTest() {
environmentVariables.set("FOO", "bar");
// use environment
// environment cleared at end
}
}
The environment variables object can also be initialised in the #BeforeEach method or constructed explicitly to have values in the initializer list of the test class.
I think You have the problem with keyword final. Remove it, and it should work,
try like this:
#Rule
public EnvironmentVariables environmentVariables = new EnvironmentVariables();
final = define an entity that can only be assigned once
so from my perspective this is messing Your run.
Hope this helps,

How to get a collection of tests in a JUnit 4 test suite

In JUnit 3, I could get all of the tests within a test suite with the following code:
TestSuite allTestsSuite = (TestSuite) AllTests.suite()
Enumeration enumeration = allTestsSuite.tests();
ArrayList listOfTests = Collection.list(enumeration);
However, I can't find an equivalent way of doing this in JUnit 4. Classes no longer have a .suite() method; they simply use the #Suite annotation. This wouldn't be a problem except that the Suite class no longer has a tests() method. There is a children() method, but that returns a list of Runners, which seem to be something different than why I'm looking for.
So how can I get the tests within a test suite in JUnit 4, like I could with JUnit 3?
The simplest way to perform any kind of filering is to create your own JUnit Categories.
See this Junit Category tutorial for more details but basically, you create your own categories named whatever you want
public interface GuiTest{ }
public interface DbTest { }
And now you can annotate either entire test classes or individual tests with that category:
#Category(GuiTest.class)
public void myJPanelTest{
#Test
public void testFoo(){
...
}
//look we can have other categories too
#Test
#Category(DbTest.class)
public void accidentalDbTest(){
}
}
Then in your test suite, you can specify to include or exclude tests that match the given category
#RunWith(Categories.class)
#IncludeCategory(GuiTest.class)
#ExcludeCategory(DbTest.class) //not sure if we need both but can't hurt
#SuiteClasses( {
...
})
public class GuiTestsOnlySuite{}
Using Categories is much better than having to come up with manually filtering tests based on ad-hoc naming conventions because it that is hard to remember to do (and to make sure everyone in your group adheres to the naming conventions) and since the categories are classes, you can use your IDE to search/refactor/ compile time check your category names.
The only downside I've seen is at least in my IDE, the tests take a little longer to run because there is extra reflection work to do to make sure the test matches your category filter criteria before it runs.
After a bit of experimentation, I discovered the following solution:
SuiteClasses suiteClassesAnnotation = AllTests.class.getAnnotation(SuiteClasses.class);
if (suiteClassesAnnotation == null)
throw new NullPointerException("This class isn't annotated with #SuiteClasses");
Class<?>[] classesInSuite = suiteClassesAnnotation.value();
Basically, it gets the classes the same way that JUnit itself gets them: by looking into the annotation and determining which values are included within it.
The category solution provided by dkatzel is also a good option if you're ultimately wanting to filter these classes, but if you need a list of classes in a suite for some other purpose such as code analysis, this is the simplest and most direct way to do it.

Can Maven Site add test method names to the class documentation?

I have a class Something and a JUnit test class TestSomething.
How can I add the test method names of TestSomething to the documentation of Something?
you can run javadoc for test classes too: see tes-javadoc goal http://maven.apache.org/plugins/maven-javadoc-plugin/test-javadoc-mojo.html

Ant junit batchtest

I have my junit test classes.I am running these class with ant.I am using batchtest attribute with parameter includes="*/ Test *.class" but i have classes with name like * test * that includes no test method and when i run it gives error "no tests found".Is there a option like if no test in the class then skip?
To answer the question you need to supply a better pattern.
Potential solution:
Refactor all legitimate test classes to BEGIN with the prefix Test and than change the ant script to this:
includes="*/Test*.class"
Why do you have classes with the name "Test" in them that aren't tests? I highly recommend following a naming convention that puts Test at the beginning and removing test from your file names that are in fact not tests.

Categories