JUnit in a Nutshell: Hello World

Home  >>  JUnit  >>  JUnit in a Nutshell: Hello World

JUnit in a Nutshell: Hello World

On August 12, 2014, Posted by , In JUnit, By ,,, , With 5 Comments

JUnit in a Nutshell is a multi-part tutorial about the essentials of JUnit testing. This Hello World chapter introduces the very basics of a test: how it is written, executed and evaluated. The post also kicks off the ongoing example, which is continuously carried forward throughout this mini-series.

Why bother?

Writing high quality software is a difficult undertaking. As for many other advocates of agile approaches extensive upfront-planning did not work out well for me. But for all that methodology I experienced the biggest advancement when we began to use consequently JUnit with TDD. And indeed, empirical studies seem to confirm my perception that this practice improves quality, as an infoQ article states1.

However JUnit testing is not as trivial as it might look. A fatal mistake we made at the beginning was to treat test classes as second rated citizens. Gradually we realized that a test is much more than a simple verification machine and – if not written with care – it can be a pain in the ass regarding maintenance and progression2.

Nowadays I tend to see a test case more as an accompanying specification of the unit under test. Quite similar to the specs of a workpiece like a cogwheel, that tells QA what key figures such a unit have to met. But due to the nature of software no one but the developer is apt to write such low level specs. By doing so automated tests become an important source of information about the intented behavior of a unit. And one that does not become outdated as easily as documentation…

Getting Started

A journey of a thousand miles begins with a single stepLao Tzu

Let us assume we have to write a simple number range counter that delivers a certain amount of consecutive integers, starting from a given value. Following the metaphor of the accompanying specification we could begin with the following code:

public class NumberRangeCounterTest {
}

The test class expresses the intent to develop a unit NumberRangeCounter, which Meszaros would denote as system under test (SUT). And following a common naming pattern the unit’s name is complemented by the postfix Test.

That is all well and good, but the impatient may wonder: What is the next step? What should be tested first? And – how do I create an executable test anyway?

There are various ways to incorporate JUnit. If you work with the Eclipse Java IDE the library is already included. It simply can be added to a project’s build path, which will be sufficient throughout this tutorial. To get your own copy please refer to Download and Install, for maven integration look at Using JUnit and if you happen to need an OSGi bundle you make a find at the eclipse orbit downloads.

Usually it is a good idea to start with the Happy Path, which is the ‘normal’ path of execution and ideally the general business usecase. For the SUT NumberRangeCounter this might be a test to verify, that the counter returns consecutive numbers on subsequent invocations of a method, which still has to be defined.

An executable JUnit test is a public, non static method that gets annotated with @Test and takes no parameters. Summarizing all this information the next step could be the following method stub3:

public class NumberRangeCounterTest {
  
  @Test
  public void subsequentNumber() {    
  }
}

Still not much, but it is actually sufficient for JUnit to run the test the first time. JUnit test runs can be launched from command line or a particular UI, but for the scope of this tutorial I assume that you have an IDE integration available. Within Eclipse the result would look like this4:

Hello World

The green bar signals that the test run did not recognize any problems. Which is not a big surprise, as we have not tested anything yet. But remember we have already done some useful considerations that can help us to populate our first test easily:

1 We intent to write a unit NumberRangeCounter that is responsible for delivering a consecutive sequence of integer values. To test it we could create a local variable that takes a new instance of such a counter.

  @Test
  public void subsequentNumber() {    
    NumberRangeCounter counter = new NumberRangeCounter();
  }

2 As the first test should assert that numbers provided by the NumberRangeCounter are consecutive integer values, meaning 5, 6, 7 or the like, the SUT could use a method providing those values. Furthermore this method could be called twice to provide a minimum set of subsequent values.

  @Test
  public void subsequentNumber() {    
    NumberRangeCounter counter = new NumberRangeCounter();

    int first = counter.next();
    int second = counter.next();
  }

Looks reasonable so far, but how can we assure that a test run is denoted as failure, if the value of second is not a valid successor of first? JUnit offers for this purpose the class org.junit.Assert, which provides a set of static methods to help developers to write so called self-checking tests.

The methods prefixed with assert are meant to check a certain condition, throwing an AssertionError on a negative result. Such errors are picked up by the JUnit runtime and mark the test as failed in the resulting report.

Update 2014/08/13: Using org.junit.Assert is just one possibility. JUnit also includes a matcher library Hamcrest, which many people consider a better solution regarding clean code. Personally I like the syntax of a third party library called AssertJ best.

I think that Assert might be more intuitive for beginners, so I choose it for this ‘hello world’ post. Due to the comments on that decision I realized that I have to mention these other possibilities at least at this point. I will elaborate on the usage of Hamcrest and AssertJ in a follow up post.

To assert that two values or objects are equals it is plausible to use Assert#assertEquals. As it is very common to use static imports for assertion method calls, the subsequentNumber test could be completed like this:

  @Test
  public void subsequentNumber() {    
    NumberRangeCounter counter = new NumberRangeCounter();

    int first = counter.next();
    int second = counter.next();

    assertEquals( first + 1, second );
  }

As you can see, the test specifies an important behaviour of the SUT, which does not even exist yet. And by the way, this also means that the test class does not compile anymore :? So the next step could be to create a skeleton of our unit to solve this problem.

Although this tutorial is about JUnit and not TDD, I have chosen to insinuate the latter approach to emphasize the specification character clean JUnit test cases can have. Such an approach shifts the work focus from the unit’s inwards more to its usage and low level requirements.

If you want to learn more about TDD, in particular the Red/Green/Refactor mantra used to implement a single unit the books Test-Driven Development By Example by Kent Beck or Test Driven by Lasse Koskela might be a good evening read.

The following snippet shows a how the NumberRangeCounter stub would look like:

public class NumberRangeCounter {

  public int next() {
    return 0;
  }
}

Running the test again, now leads to a red bar due to the insufficient implementation of NumberRangeCounter#next(). This allows to ensure that the specification has not been met accidently by a useless verification or the like:

redbar

Additionally to the red bar the execution report shows how many tests have been run in total, how many of those terminated with errors, and how many have failed due to wrong assertions. A stacktrace for each error/failure helps to find the exact location in the test class.

An AssertionError provides an explanatory message, which is shown in the first line of the failure trace. Whereas a test in error may indicate an arbitrary programming mistake, causing an Exception to be thrown beyond the test’s assertion statements.

Note that JUnit follows the all or nothing principle. This means if a test run involves more then one test, which is usually the case, the failure of a single test marks the whole execution as failed by the red bar.

As the actual implementation of a particular unit is of minor interest for the topic of this article, I leave it up to you to come up with an innovative solution to make our first test pass again ;-)

Hello World Summary

The previous sections explained the very basics of a JUnit test – how it is written, executed and evaluated. While doing so I placed value on the fact that such tests should be developed with the highest possible coding standards one could think of. The given example was hopefully well-balanced enough to provide a comprehensible introduction without being trivial. Suggestions for improvements are of course highly appreciated.

The next JUnit in a Nutshell post will continue the example and cover the general concept of a test case and its four-phase test structure, so stay tuned.

Chapter Navigation
Table of Content | Next 
  1. Other studies are listed at http://biblio.gdinwiddie.com/biblio/StudiesOfTestDrivenDevelopment and a comparative analysis of empirical studies can be found at https://tuhat.halvi.helsinki.fi/portal/files/29553974/2014_01_swqd_author_version.pdf
  2. See also: Keeping Tests Clean, Clean Code, Chapter 9, Robert C. Martin 2009
  3. There are diverging opinions on how to name a test method. I have written down some considerations about this topic in Getting JUnit Test Names Right
  4. For more information on how to work with JUnit in Eclipse you might like to read my post Working Efficiently with JUnit in Eclipse
Follow me

Frank Appel

Frank is a stalwart of agile methods and test driven development in particular. He understands software development as a craftsmanship based on a well-balanced mix of knowledge and the experience of the daily work.

fappel@codeaffine.com
Follow me

Latest posts by Frank Appel (see all)

5 Comments so far:

  1. daniel says:

    I prefer assertThat with Hamcrest matchers

    • Frank Appel says:

      Daniel,

      personally I like AssertJ assertions best, but I thought the ‘classic’ Assert#assertXXX approach would be best for a beginnner tutorial. Probably I will provide a section about advantages of the various assertion possibilities in a follow up post.

      Frank

      • Christian says:

        Especially in beginner tutorials you should show how to do it “right”! Beginners tend to stick with what they see in examples. And AssertJ has a much better syntax and should be better for beginners, too.

        • Frank Appel says:

          I share your assessment regarding AssertJ but I am not sure if this is really the more intuitive solution for beginners. Recently I even was criticized for using a AssertJ snippet in a post, where the commenter claimed that he ‘fails to see the point of these mini-DSLs‘ and that they would be in no way more expressive than using Assert.assertXXX methods.

          So I struggle a bit opting for matcher library right away. However I see that this is a topic that has to be worked off in the JUnit in a Nutshell series. So I would be happy to here from you people, what approach you prefer and why. This would surely help me to provide a balanced description. Comments, mails, tweets or whatsoever are welcome :-)

  2. […] JUnit in a Nutshell – This outstanding tutorial from Frank Appel covers the fundamentals of test driven development on JUnit with proper test structure, test isolation, and test runners. Learn how to get up and running with plenty of examples and best practices. […]

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>