Given-When-Then: Writing Unit Tests in 3 Lines

Monday, March 18, 2013 @ 04:59

By: Corey Adler, Staff Developer

When it comes to unit tests, most people will agree that there is some value to writing and maintaining them. Unit tests, especially in a TDD environment, can force programmers to think about how they want to design their application and to create applications that are extensible and flexible to change. Unit tests can help create clean code for your application, but there’s nothing to prevent you from writing tests that are not so clean. You might be correctly testing a certain function, but the programmer sitting next to you might have no idea what exactly your test is doing if your test code isn’t properly written. To solve this, I would like to introduce you to the 3-line rule that I try my best to achieve when creating my own tests: Every test method should only have 3 lines of code in them.

Here’s how it works, using Figures 1 and 2 below (which is testing a calculator program):

Figure 1: The Calculator class

Figure 2: The 3 line unit test with Given-When-Then (this uses the NUnit testing framework)

Given: These are any and all assumptions that you’re making in this test. Oftentimes, this will end up being just instantiating whatever objects will be needed for the rest of the test. In Figure 1, the only assumption being made is that you have a Calculator object that’s ready to do whatever calculations in has on it. This is a very simple example, but you could easily think of more complex examples, possibly dealing with mocking out service objects that get injected into other classes.

When: This is the action that’s going to take place. Most of my When methods are actually just one line in length (i.e. make a call to a particular method and store the result). For the Calculator, this would be a call to whatever Add function has been implemented, and passing in the two numbers from the test case definition to that method. The result would inevitably be stored in a variable that is accessible from anywhere in the test class itself.

Then: This is where the test determines if the result of the Given and When sections meets what was expected in the test. All of the assertions are done in this method itself. In the calculator example above this would assert that the two numbers were added together correctly in the Calculator object, and that result sent back is both not null and equals the correct result.

Now, let’s think about what happens when a programmer or a manager takes a look at this test later (possibly even years later), compared to doing tests without them. Undoubtedly they will be able to tell right away what exactly is being tested just from those 3 lines! Also, think about what would happen in the future if the test breaks. From those 3 lines you can see the exact feature that’s not working (i.e. that the Calculator is now no longer adding 2 numbers correctly. You can then dive into the method call from the When section of the test to see what exactly is going wrong.

It’s fast to debug, clean to write, easy to read, and will help future developers who don’t code the same way that you do. It’s what I do whenever I write my unit tests, and I hope you will too. Until next time, I wish you good coding.