Juri Strumpflohner
Juri Strumpflohner Juri is a full stack developer and tech lead with a special passion for the web and frontend development. He creates online videos for Egghead.io, writes articles on his blog and for tech magazines, speaks at conferences and holds training workshops. Juri is also a recognized Google Developer Expert in Web Technologies

TDD, JUnit 3.8 and JUnit 4

4 min read

I don't know whether you already got in touch with Unit testing or TDD (Test-driven development). At least you should if you're developing software in a more "professional" manner.
I personally first encountered unit-testing and TDD at the University. Initially you actually don't get the point about it. Ok, I mean, you see that it is necessary and that it should be done, however when you start programming afterwards, testing is always something annoying, something you do because your professor says that is has to be done. You usually want to continue hacking your problem instead to do boring testing. I started to "enjoy" (big quotes :D ) testing mainly when I started to develop larger and more complex applications which I did during one of the last projects at the University and when I developed the application for my thesis project. Initially you force yourself to write the test-cases but once you have quite a lot of features implemented and you have to do large changes (which you have for sure) then you get it why you wrote those tests. If they have been well written they'll save your life since they guarantee that all the previously implemented functions still work also after you performed all the necessary changes. Without tests you cannot identify whether all of the features of your software still work and therefore you will try to avoid with all of you energy any big change to your system (probably disappointing your customers).
What I would like to suggest and which worked quite well for me till now is to proceed in a test-driven development style (TDD, one of the XP practices). A test-driven development cycle usually looks as follows:
  1. Write a test for the next bit of functionality you have in mind. The test should succeed only when the functionality has been implemented correctly.
  2. Make the test compile by creating stubs for all the missing classes and methods referenced by the test.
  3. Run the test. It should fail.
  4. Implement just enough functionality to get the test to succeed (proceed aggressively by hacking the problem).
  5. Clean up the implementation as much as possibly, typically by removing duplication (do refactoring).
As I'm developing a lot in Java, I usually used the JUnit 3.8.1 library within the Eclipse IDE. Recently when I started to develop a new project (I will announce more details after its first release ;) ) I switched to the JUnit 4 library. There are some drastic changes. While the 3.8.1 version was using naming conventions and reflection for locating tests (for which reason it also extended from the junit.framework.TestCase), the new version doesn't extend any class. It uses the annotation mechanism instead. So for instance an old JUnit 3.8 test looked as follows:

import junit.framework.TestCase;

public class TestAdder extends TestCase{
public TestCase(){
...
}

public void testAdd(){
...
}
}

...the same test written for the JUnit 4 framework would look like this

public class TestAdder{
public TestCase(){
...
}

@Test
public void testAdd(){
...
}
}
This has the main advantage is that one is no more bound on naming conventions such as all test-methods have to look like "testFoo()", although I personally didn't found those conventions bad at all.
JUnit 3 test usually call the setUp() method for doing variable initializations, logging and some other stuff before starting the tests and after each tested method the tearDown() method is invoked. In JUnit 4 these methods don't exist any more, but they are - as you probably already mentioned - substituted with the appropriate @Before and @After annotations. In this way you're free to choose your own name for the setUp() or tearDown() method by just adding the right annotation.
Another thing JUnit 3 testers will probably miss is that there is no suite() nor a GUI runner. So what I encountered when writing the new version 4 tests is that the integrated Eclipse JUnit 3 runner clearly doesn't find the tests since they don't dispose of a suite() method. To gain backwards compatibility the TestCase has therefore to be wrapped in a JUnit4TestAdapter (see sample below) such that it can be invoked by the Eclipse JUnit runner.
...
public static junit.framework.Test suite() {
return new JUnit4TestAdapter(FileSystemManagerTest.class);
}
...where "FileSystemManagerTest" has clearly to be substituted with the name of the TestCase.

To summarize I have to say that moving from JUnit 3 takes some time till one gets accustomed to JUnit 4, but as soon as these mentioned differences are known everything remains quite similar. Still tests cannot be automatically reverse engineered from existing source code :D
Questions? Thoughts? Hit me up on Twitter
comments powered by Disqus