JUnit4to5 translation powered by ANTLR.
./gradlew build
./compile-grammar-java.sh./junit4to5-translator.sh <path>Non-Static:
org.junit.Assert->org.junit.jupiter.api.Assertionsorg.junit.Before->org.junit.jupiter.api.BeforeEachorg.junit.BeforeClass->org.junit.jupiter.api.BeforeAllorg.junit.After->org.junit.jupiter.api.AfterEachorg.junit.AfterClass->org.junit.jupiter.api.AfterAllorg.junit.Ignore->org.junit.jupiter.api.Disabled
Static:
org.junit.Assert.*->org.junit.jupiter.api.Assertions.*org.junit.Assert.assertArrayEquals->org.junit.jupiter.api.Assertions.assertArrayEqualsorg.junit.Assert.assertEquals->org.junit.jupiter.api.Assertions.assertEqualsorg.junit.Assert.assertNotEquals->org.junit.jupiter.api.Assertions.assertNotEqualsorg.junit.Assert.assertSame->org.junit.jupiter.api.Assertions.assertSameorg.junit.Assert.assertNull->org.junit.jupiter.api.Assertions.assertNullorg.junit.Assert.assertNotNull->org.junit.jupiter.api.Assertions.assertNotNullorg.junit.Assert.assertTrue->org.junit.jupiter.api.Assertions.assertTrueorg.junit.Assert.assertFalse->org.junit.jupiter.api.Assertions.assertFalseorg.junit.Assert.assertThrows->org.junit.jupiter.api.Assertions.assertThrowsorg.junit.Assert.fail->org.junit.jupiter.api.Assertions.failorg.junit.Assume.assumeTrue->org.junit.jupiter.api.Assumptions.assumeTrue
org.junit.runner.RunWithorg.junit.Ruleorg.junit.runners.Parameterizedorg.junit.runners.Parameterized.Parametersorg.junit.Testorg.junit.rules.TestName
Once the imports to be removed and to be added are identified, then an algorithm to detect import groups is applied to maintain a coherence in the replacement.
Rules responsible for setup data before test execution, now need to be called explicitly in the before each hook, in case it’s absent the hook is created with the setupRule call.
* I took care to add the call only if the call doesn’t exists in the code.
This was not an easy one, it involves replacing the instance variable usages by the TestInfo argument provided in JUnit5 methods.
First, remove the rule instance variable.
Next, replace the old rule by the TestInfo argument from JUnit5.
This should work even when this usage comes from nested methods.
* The nested level can be bigger than one, and it can happens to be in the parent class.
There are also some cases where the rule is used in nested classes.
Replacement:
@RunWith(SpringJUnit4ClassRunner.class)->@ExtendWith(SpringExtension.class)@RunWith(MockitoJUnitRunner.class)->@ExtendWith(MockitoExtension.class)
Removal:
@RunWith(DataProviderRunner.class)@RunWith(Parameterized.class)
@Before->@BeforeEach@BeforeClass->@BeforeAll@After->@AfterEach@AfterClass->@AfterAll
@Ignore->@Disabled
In this case the expected argument needs to be removed, and the same exception from the argument needs to be used with an assertThrows call inside the method.
This is very simple, it’s a matter of removing the @DataProvider annotation.
And in the test itself, it’s just a matter of replacing the annotations for the test and for the input source.
However, there are some cases a bit more involved, when the location argument is provided, in which case the fully qualified name needs to be built.
It’s just a matter of replacing the annotations.
For booleans and ints, it’s needed to remove the quotes as JUnit5 expects the primitive values accordingly with the type.
When the input parameter is of an enum type, then the @EnumSource annotation is used.
Methods like assumeTrue and assertEquals have the description argument position changed.
There is not a direct replacement for this class. It was needed to remove the extends clause and detect any usages of the methods inherited and then to apply the appropriate changes. An example of this is the assertEquals, the TestCase class brings it, so when it’s used it’s needed to add the import org.junit.jupiter.api.Assertions.assertEquals.
The JUnit5 convention is not use the public access modifier for the test class, hooks and test methods. However, not always this can be removed, because the tests can have cross-references between them. Metadata is used to detect if that is the case to avoid breaking the code.
Finally, the program applies some formatting to avoid any translation generates lines longer than 120 characters.