Friday, April 15, 2011

Best way to automagically migrate tests from JUnit 3 to JUnit 4?

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?

From stackoverflow
  • 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.

    VonC : Do 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')
  • Not answering the question, but you do realize that you can run JUnit3 tests under JUnit4 without modification, yes?

    skaffman : Unless you use Junit3 `TestSuite`, in which case you're stuffed.
  • 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.

  • In my opinion, it cannot be that hard. So let's try it:

    @Test annotation

    All methods beginning with public void test must precede the @Test annotation. This task is easy with a regex.

    Get rid of extends TestCase

    Remove exactly one occurence per file of the string

    " extends TestCase"
    

    SetUp and TearDown methods

    Eclipse generates following setUp() method:

    @Override
    protected void setUp() throws Exception { }
    

    Must be replaced by:

    @Before
    protected void setUp() throws Exception { }
    

    Same for tearDown():

    @Override
    protected void tearDown() throws Exception { }
    

    replaced by

    @After
    protected void tearDown() throws Exception { }
    

    Imports

    The imports has to be reorganized:

    1. Remove import junit.framework.TestCase;
    2. Add org.junit.*; or import org.junit.After; import org.junit.Before; import org.junit.Test;

    Remove main methods?

    Probably it's necessary to remove/refactor existing main methods that will execute the test.

    Convert suite() method to @RunWithClass

    According to saua's comment, there must be a conversion of the suite() method. Pattern will follow. Thanks, saua!

    Conclusion

    I think, it's done very easy via a set of regular expressions, even if it will kill my brain ;)

    Don : The imports can be cleaned up automatically by Eclipse (Ctrl + Shift + O)
    furtelwart : I don't think, that he wants to do this with a bunch of files. And they should be runnable.
    Joachim Sauer : I'd add conversion of suite() methods to @RunWith(Suite.class) @SuiteCkasses()
  • @Jeffery Fredrick

    Using the old JUnit 3 classes with JUnit 4 without doing a full conversion causes other problems. For Example, the @BeforeClass was being ignored when I first converted to JUnit 4 and added the @BeforeClass annotation.

    The story turns out to be is if JUnit 4 sees a subclass of junit.framework.TestCase it will run the tests in the old style, which means annotations like @BeforeClass get ignored.

  • 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!

0 comments:

Post a Comment