I have a bunch of JUnit 3 classes which extend TestCase and would like to automatically migrate them to be JUnit4 tests with annotations such as @Before
, @After
, @Test
, etc.
Any tool out there to do this in a big batch run?
-
1Not answering the question, but you do realize that you can run JUnit3 tests under JUnit4 without modification, yes? – Jeffrey Fredrick Nov 11 '08 at 08:44
-
2Unless you use Junit3 `TestSuite`, in which case you're stuffed. – skaffman Oct 30 '09 at 09:53
-
6If you keep those JUnit 3 tests around, other developers (depending on your team size) will keep copying them to new tests. And if they need to temporary disable a test (yes, the shouldn't, but sometimes they will need to), they 'll keep renaming it from testX to FIMXEtestX instead of annotating it with @Ignore. So you won't have any idea how many tests are currently being ignored (so how worried you should be). Just take any big project and look for regex "public void \w+test" – Geoffrey De Smet Dec 24 '10 at 08:54
7 Answers
In my opinion, it cannot be that hard. So let's try it:
0. Imports
You need to import three annotations:
import org.junit.After;
import org.junit.Before;
import org.junit.Test;`
After you've made the next few changes, you won't need import junit.framework.TestCase;
.
1. Annotate test*
Methods
All methods beginning with public void test
must be preceded by the @Test
annotation.
This task is easy with a regex.
2. Annotate SetUp and TearDown methods
Eclipse generates following setUp()
method:
@Override
protected void setUp() throws Exception { }
Must be replaced by:
@Before
public void setUp() throws Exception { }
Same for tearDown()
:
@Override
protected void tearDown() throws Exception { }
replaced by
@After
public void tearDown() throws Exception { }
3. Get rid of extends TestCase
Remove exactly one occurence per file of the string
" extends TestCase"
4. Remove main methods?
Probably it's necessary to remove/refactor existing main methods that will execute the test.
5. Convert suite()
method to @RunWithClass
According to saua's comment, there must be a conversion of the suite()
method. Thanks, saua!
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestDog.class
TestCat.class
TestAardvark.class
})
Conclusion
I think, it's done very easy via a set of regular expressions, even if it will kill my brain ;)
-
The imports can be cleaned up automatically by Eclipse (Ctrl + Shift + O) – Dónal Mar 24 '09 at 13:21
-
I don't think, that he wants to do this with a bunch of files. And they should be runnable. – guerda Mar 24 '09 at 13:23
-
2I'd add conversion of suite() methods to @RunWith(Suite.class) @SuiteCkasses() – Joachim Sauer Mar 27 '09 at 13:12
-
2
-
One additional step that I needed was to add @RunWith(JUnit4.class) to my class + import those things: import org.junit.runner.RunWith; import org.junit.runners.JUnit4; – allyourcode May 15 '13 at 20:53
-
need to convert the fail(string) and assertXX(...) calls to respective classes, as we do not extend TestCase – tgkprog Jun 06 '13 at 14:29
Here are the actual regular expressions I used to execute furtelwart's suggestions:
// Add @Test
Replace:
^[ \t]+(public +void +test)
With:
@Test\n $1
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Remove double @Test's on already @Test annotated files
Replace:
^[ \t]+@Test\n[ \t]+@Test
With:
@Test
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Remove all empty setUp's
Replace:
^[ \*]+((public|protected) +)?void +setUp\(\)[^\{]*\{\s*(super\.setUp\(\);)?\s*\}\n([ \t]*\n)?
With nothing
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Add @Before to all setUp's
Replace:
^([ \t]+@Override\n)?[ \t]+((public|protected) +)?(void +setUp\(\))
With:
@Before\n public void setUp()
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Remove double @Before's on already @Before annotated files
Replace:
^[ \t]+@Before\n[ \t]+@Before
With:
@Before
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Remove all empty tearDown's
Replace:
^[ \*]+((public|protected) +)?void +tearDown\(\)[^\{]*\{\s*(super\.tearDown\(\);)?\s*\}\n([ \t]*\n)?
With nothing
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Add @After to all tearDown's
Replace:
^([ \t]+@Override\n)?[ \t]+((public|protected) +)?(void +tearDown\(\))
With:
@After\n public void tearDown()
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Remove double @After's on already @After annotated files
Replace:
^[ \t]+@After\n[ \t]+@After
With:
@After
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Remove old imports, add new imports
Replace:
^([ \t]*import[ \t]+junit\.framework\.Assert;\n)?[ \t]*import[ \t]+junit\.framework\.TestCase;
With:
import org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\nimport static org.junit.Assert.*;
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Remove all extends TestCase
Replace:
[ \t]+extends[ \t]+TestCase[ \t]+\{
With:
{
Regular Expression: on
Case sensitive: on
File name filter:
*Test.java
// Look for import junit.framework;
Find:
import junit\.framework
Manually fix
Regular Expression: on
Case sensitive: on
// Look for ignored tests (FIXME, disabled, ...)
Find:
public[ \t]+void[ \t]+\w+test
Manually fix
Regular Expression: on
Case sensitive: on
// Look for dummy/empty tests
Find:
public[ \t]+void[ \t]+test[\w\d]*\(\s*\)\s*\{\s*(//[^\n]*)?\s*\}
Manually fix
Regular Expression: on
Case sensitive: on
Note: it's important to do them in the order shown above.

- 26,223
- 11
- 73
- 120
-
-
Yes. In IntelliJ, do "Replace in path" (ctrl-shift-r) and fill in that dialog for each of these. For those that need to be done manually, use "Find in path" (ctrl-shift-f). – Geoffrey De Smet May 17 '13 at 08:27
-
[Same question for JUnit 4 to JUnit 5](https://stackoverflow.com/questions/46242083/how-to-automatically-migrate-from-junit-4-to-junit-5) – Geoffrey De Smet Feb 09 '18 at 10:26
We are in the middle of migrating a reasonably large code base to JUnit4. Since this is the second time I'm doing a migration such as this, I decided to save the code somewhere:
https://github.com/FranciscoBorges/junit3ToJunit4
It deals with more corner cases than the ones enumerated in answers above. Such as:
- calls to
TestCase.setUp()
andTestCase.tearDown()
- calls to
TestCase(String)
constructor within a sub-class constructor - calls to
TestCase.assert*
methods that moved toAssert
. - fixing package names
junit.framework
toorg.junit
- etc

- 3,980
- 1
- 23
- 27
I don't know of a tool that would do this at the moment - I'd expect Eclipse to provide some plugin fairly shortly - but you could knock up a simple source tree exploring Java class that would do it for you if you only want to do a basic conversion. I had to write something similar to automatically generate skeleton test cases for a legacy application so I've got a fair amount of the support code already. You're welcome to use it.

- 7,167
- 3
- 38
- 57
-
2Do you use java6 AST feature or eclipse AST ? Anyway, I am interested also: may be you may consider making this question a 'code-challenge' and publish your anonymized code on DZones ? (see http://stackoverflow.com/questions/190007 for an example of 'code-chalenge') – VonC Nov 05 '08 at 12:10
There are, to my best knowledge, no available migration tools (yet). What I know is this:
Last year, at OOPSLA in Nashville, was a paper about API migration but alas their tools seems not be openly available. I'll provide the link to the paper, (even though I dare it is of little use for you since it is rather theory heavy): "Annotation Refactoring: Inferring Upgrade Transformations for Legacy Applications".
Above, I wrote "no available tool (yet)" because my student Lea Hänsenberger is currently working on an auotmated API migration from, not onyl, JUnit 4 a to JExample, but also from JUnit 3 to JUnit 4. Please follow JExample on Twitter to get notified when she releases a first beta.
I hope this information was of help for you.

- 27,477
- 2
- 76
- 91
Nice post. I did the upgrade using Netbeans with the following RegEx strings: (First line search-string, second one replace-string)
public void test
@Test\n public void test
@Override\n.*protected void onSetUp
@Before\n protected void onSetUp
@Override\n.*protected void onTearDown
@After\n protected void onTearDown
Don't forget to flag the Regular Expression checkbox!

- 184
- 10
If you want to automatically convert your Junit3 tests to Junit4, you can use the Vogella's Codemodify tool, available at this address:
TL;DR install and use it as follows:
- get Eclipse if you don't use it already (it's open source)
- From menu: Help > Install new software, then paste the update site http://dl.bintray.com/vogellacompany/junit-4-tools/ in the Work With field
- Finish the installation, and restart if needed.
Then, you can right-click any Junit3 test class, and select the Source > Convert to JUnit4 menu entry to convert your class to JUnit4.
The tool will automagically remove TestCase parent, outdated imports, add @Before, @After, @Test annotations, etc.

- 2,187
- 1
- 17
- 21