11 things I learned about TDD by looking at the tests in the JUnit source

JUnit is a unit testing framework for the Java programming language. JUnit has been important in the development of test-driven development, and is one of a family of unit testing frameworks which is collectively known as xUnit that originated with SUnit.

JUnit was originally written by Erich Gamma and Kent Beck. The latter literally wrote the book on Test Driven Development.  I thought it would be worthwhile to look at some of the tests in the library and draw attention to some interesting things about them because it may change people’s ideas of how to practice TDD.

TDD is often explained in overly simple terms and this is probably done to increase adoption.  Unfortunately, if you jump right in without a mentor, you will most likely approach the process in the wrong way.  I think a lot of people usually wander blind in the woods and when they finally find their way out, they’ve picked up some dogma and cargo cult practices along the way.

My hope is that pointing out some of these interesting things about these tests will make people change their mind about how they practice TDD in the future.  Or, if you already do these things I’m about to mention, it may reassure you that you’re practicing TDD the right way.

I know that Kent Beck didn’t write all these tests himself, but I’m confident he or someone he trusts code reviews them before they get committed to the project.  I also want to say to take all of these things with a grain of salt.  These were tests written for JUnit, not the project you’re working on.  Just because the JUnit tests are written a certain way doesn’t mean that’s the best way to write your tests.  But, it’s a great reason to consider doing so.

You do not have to mock out every collaborator

If you follow into assertArrayEquals , you’ll see that it eventually calls  internalArrayEquals  which uses the  ExactComparisonCriteria  directly instead of mocking it out.  The takeaway is, you don’t have to mock every collaborator.

You don’t have to write a test class for every production class

The production code has a package named  org.junit.internal and it’s rare to find test code directly testing the classes or methods in that package.  Instead, this code is indirectly tested by testing code that uses the classes in the org.junit.internal  package.  This is probably done to make it easier to refactor code without tests interfering.  You can read more about this technique here.

You can have multiple asserts in one test

Your test package does not have to be the same package as the System Under Test

For example, there is a test named JUnit4ClassRunnerTest  that is in the org.junit.tests.deprecated  package, but it is testing a class in the  org.junit.internal.runners  package.

Your test classes can get kind of long, but your test methods should be pretty short

For example, the  org.junit.tests.assertion.AssertionTest  is close to 700 lines of code.  But that is distributed between 80+ tests!  Here’s an average sized one:

Because this code is so short, it’s very easy to figure out what it’s doing.

The names of local variables in your test are not that important

I see lots of local variables in tests with very poor names like a  and o .  But, as you can see, the tests are so straight forward that it doesn’t hinder readability.

It’s ok to create nested classes inside your test classes

Nested classes are defined all over the tests.  It’s relatively rare to find top level classes in the test package that aren’t test classes, test suites, or test runners.  To relate this back to me, I’ve built a lot of FooBuilder’s in the past to make it easier to create production classes, but concepts like that don’t seem to exist in the JUnit test code.  I did find a few classes that look like this at the top level:

I’m not sure why they decided to create this class at the top level, but a lot of other classes are nested in tests.  My first impression is it has to do with whether the class will be reused in other tests are not, but the nested classes have a lot of duplication in them so that does not seem to be the reason.

Like this section says, it’s ok to nest classes in your tests, but from JUnit’s perspective, this isn’t a rule.  It’s just a slight preference.

Assertions should almost always be at the end of a test

It was very rare for me to find tests that were written like this:

Most of the time, they were written like this:

Every test has at least one assert

Every test I’ve seen has at least one assert somewhere.  In the past I have written tests that assert nothing.  Their purpose was to check that I can create production classes or run methods without an error occurring (e.g., testInitializingFooDoesNotError() ).  Based on this analysis, I’m going to stop doing that in the future.

You do not have to use a mocking framework or mocks

None of the tests I found use a mocking framework.  In fact, technically I couldn’t find tests that use mocks.  But there are a lot of tests that use stubs.  This is an article on the difference, if you’re interested.

Every time I see some code that requires a parameter, that parameter is a real class, not a mock:

You should definitely take this part a grain of salt though.  For all I know, the JUnit team would use a mocking framework if they could.  What makes it extra tricky is a lot of the test doubles they create need specific annotations on them and mocking frameworks may make that difficult to do.

You can create a test class for something that is not a production class

A lot of people write one test per production class.  Sometimes that’s true for JUnit tests, but not always.  For example there is a test named  org.junit.tests.running.methods.AnnotationTest , but there is no  Annotation  class.  This is just testing that the JUnit annotations (of which there are many) work correctly.

You can create your own, higher level asserts in your test

Here, the test method is very short, but it calls another method that does some complex logic for the assertion named  assertResultSerializable() .  By the way, if you look at the implementation of that method, this is one of the rare examples I found where assertions are spread out between logic.  Usually all the assertions are at the end of a method.

Conclusion

I hope you found this exercise interesting.  One of the great things about open source is the ability to download and read a famous project and try to become a better developer by inspecting it.

Join the email list for bonus content.

3 thoughts on “11 things I learned about TDD by looking at the tests in the JUnit source

  1. vignesh says:

    I thing it is only applicable for java till 1.5 through a refference of my knowledge….. Let me know that, Is it applicable for java 1.7?

Leave a Reply

Your email address will not be published. Required fields are marked *