JUnit 5 -- reuse a nested test class with different state? - junit

Student here. In JUnit 5, what is the best way to invoke a #Nested test class multiple times, but with slightly different state each time?
I see that JUnit 5 has an (experimental) #ParameterizedTest feature that is based on the (non-experimental) #TestTemplate feature, but both of those apply to test methods only, rather than nested test classes.
I have a heavy #Nested test class that needs to be invoked once for each value of an enum (preferably with a distinct #Tag value for each invocation), and I would prefer to avoid the "copy-and-paste" method of parameterization.

It is not currently possible to execute a test class multiple times in JUnit Jupiter.
To participate in the discussion, see the following issue: https://github.com/junit-team/junit5/issues/878

Related

Is it possible to specify which Before method runs in JUnit, and if so, how?

I have a test suite which tests two different things in the same class. I have a before method that initialises some fields for the test methods to use. However, I have a group of test methods that uses the first set of field, and another group that uses the second, but not the first. I know it's possible to split the before action over different before methods, but is it also possible to specify which one runs before each test?
Concrete example:
#Before
public void before1() {...}
#Before
public void before2() {...}
#Test
public void test1() {
//Only before1 runs
}
#Test
public void test2() {
//Only before2 runs
}
This is a simple representation, but I have much more tests that use either of these befores.
Everything you've stated in your question is pointing to splitting up your tests into 2 separate classes. I am guessing that the two groups you have are testing distinct features of your code and may even have some commonality in the test names. Take all of the tests that require before1 into a test class and all the tests that require before2 into another test class. You can name these new test classes according to the grouping of behaviour you're testing.
For example if half of your tests are for success scenarios and half are testing failure scenarios, put these into classes named something like FooSucceedsTest and the failures into FooFailsTest.
There is no guarantee on the order of a #Before executing just as there's no guarantee on a #Test order of execution.
The solution is to do any setup a test is dependent on in the #Test itself and use the #Before for common setup before test execution.

How to execute different #Before in JUnit

Currently If I write #Before method, it will be executed for each of tests present in the JUnit. However i want the following.
I need to have multiple #Before methods and only needed should be executed for each test.
Example:
#Before
setUpBeforeForTest1AndTest3()
#Before
setUpBeforeForTest2AndTest4()
For test1 and test2, setUpBeforeForTest1AndTest3() should be executed and for other tests setUpBeforeForTest2AndTest4 should be executed.
How i can acheive this?
you can not achieve that this way.
To do this, make 2 distinct test classes, one with test 1 and test 3, one other with test 2 and test 4.
If you have common methods needed in all your test classes either externalize them in a helper or make a super class (usually called 'TestBase' or something similar) providing them.
You can use Junit
#Rule TestName
Then in your
#Before, depending on the test method name, do something differently.

Guideliness to write junit test cases for if,loop and exception

I'm new to Junit. I want to write test cases for if condition,loops.
Do we have any guidelines or procedure to write test cases for if,loop conditions?
Can anyone explain with an example?
IF Age < 18 THEN WHILE Age <> 18
DO ResultResult = Result +1 AgeAge = Age +1 END
DO Print “You can start driving in {Result} years”
ELSE
Print “You can start driving now!”
ENDIF
You want one test case for each major scenario that your code is supposed to be able to handle. With an "if" statement, there are generally two cases, although you might include a third case which is the "boundary" of the two. With a loop, you might want to include a case where the loop is run multiple times, and also a case where the loop is not run at all.
In your particular example, I would write three test cases - one where the age is less than 18, one where the age is exactly 18, and one where the age is over 18. In JUnit, each test case is a separate method inside a test class. Each test method should run the code that you're testing, in the particular scenario, then assert that the result was correct.
Lastly, you need to consider what to call each test method. I strongly recommend using a sentence that indicates which scenario you're testing, and what you expect to happen. Some people like to begin their test method names with the word "test"; but my experience is that this tends to draw attention away from what CONDITION you're trying to test, and draws attention toward which particular method or function it is that you're testing, and you tend to get lower quality tests as a result. For your example, I would call the test methods something like this.
public void canStartDrivingIfAgeOver18()
public void canStartDrivingIfAgeEquals18()
public void numberOfYearsRemainingIsShownIfAgeUnder18()
From my understanding of writing in junit for java ,we were used to create a source code into different blocks is the code conventional,and used to pass the values as args to the function from the test cases so the values will steps into the block statements ,and passes the test cases .
For example you are having the variable as age by assuming as functionName(int age), for testing you should pass the integer from the test case as functionName(18) it will steps into the statements and will show you the status of the test case.Create test case for a testing class write test case for the functions
UseClass classObj=new UseClass();// it should be your class
#Test
public void testValidateAge() {
classObj.validateAge("20");
assertEquals(200,"");
}
Correct me if 'm wrong :)

Junit test class variable scope

I have a Junit test class with two tests in it. test 1 will add an element to an ArrayList and passes it to the main class to do some logic and returns true. Test two should use the same arrayList and calls the same main class do the same logic but by the time the list comes to second test methods, its getting null.
I declared it as class variable. My questions is.. when I assign values to a class variable in a test method, will I not have access to the values in next test method? If yes, how should i retain the values.
Thanks,
Mahi
The way variables work in jUnit is that they get initialized before each test. So if you added value x to a list in Test1, it won't be there when you run Test2. If you want to some kind of initialization before each test, use the setup method.

JUnit Reports -- Test Method Descriptions

I am trying to see if there is a way to include "descriptive text" in my junit reports by way of javadocs. JUnit 4 doesnt seem to support the 'description' attribute for the #Test annotation like TestNG does.
So far from what I have researched there is only one tool out there called javadoc-junit (http://javadoc-junit.sourceforge.net/). However I could not get this to work since it seems to be incompatible with Junit 4.
What I want is some way to provide a sentence or two of text with my each test method in the JUnit report. JavaDoc is no good since the target audience will have to swtich between JavaDoc and the Junit Report to see documentation and/or test stats.
Anyone know of anything else I could use with minimal effort?
Best,
Ray J
In JUnit 5 there is a way to annotate every test with a #DisplayName. The declared test classes can have text, special characters and emojis.
The declared text on each test is visible by test runners and test reports.
The Javadoc says:
public #interface DisplayName
#DisplayName is used to declare a custom display name for the annotated test class or test method.
Display names are typically used for test reporting in IDEs and build tools and may contain spaces, special characters, and even emoji.
And the User Guide:
import org.junit.gen5.api.DisplayName;
import org.junit.gen5.api.Test;
#DisplayName("A special test case")
class DisplayNameDemo {
#Test
#DisplayName("Custom test name containing spaces")
void testWithDisplayNameContainingSpaces() {
}
#Test
#DisplayName("╯°□°)╯")
void testWithDisplayNameContainingSpecialCharacters() {
}
#Test
#DisplayName("😱")
void testWithDisplayNameContainingEmoji() {
}
}
There's also rather recent solution called Allure. That's a Java-based test execution report mainly based on adding supplementary annotations to the code. Existing annotations include:
custom description: #Description("A cool test")
grouping by features or stories: #Features({"feature1", "feature2"}), #Stories({"story1", "story2" })
marking methods executed inside test case as steps: #Step (works even for private methods)
attachments: #Attachment(name = "Page screenshot", type = "image/png")
See their wiki and example project for more details.
I don't put javadocs in JUnit tests. I usually make the name of the method descriptive enough so it's as good as or better than any comment I could come up with.
I could imagine, that the Framework for Integrated Tests (FIT) would be a nice and clean solution.
What does FIT do?
FIT is a framework that allows to write tests via a table in a Word document, a wiki table or an html table.
Every character outside of a table is ignored by FIT and let you enter documentation, description, requirements and so on.
How does on of these tables look like?
Imagine a function MyMath.square(int) that squares it's input parameter. You have to build a so called Fixture, being an adapter between your MyMath and the following table:
class.with.Fixture.Square
x square()
2 4
5 25
The first column describes input values, the second the expected result. If it's not equal, this field is marked as red.
How does a Fixture look like?
For the given example, this would be the correct fixture:
package class.with.Fixture // Must be the same as in the fist row of the table
public class Square extends Fixture {
public int x; // Must be the same as in the second row
public int square() { // Must be the same as in the second row
return MyMath.square(x);
}
}
Probably, you can use FIT for your requirements.
Feel free to comment my answer or edit your question for more information!