The goal of this post is not to stress the importance of writing unit tests or (TDD) process. There are plenty of articles out there that make the case for those and introduce various approaches to unit testing. Instead, I will share my experience writing what I think are effective and unit tests. The code examples are in and JUnit 4. Test Driven Development self-documenting Java Writing unit tests is fun if… you follow a methodology which enables you to write tests faster. consistent your test code is broken down into manageable small chunks (units of work). your test methods use effective, easy-to-follow naming convention and structure. you can quantify your progress by generating code coverage reports via tools like . JaCoCo This article concentrates on the first 3 items on this list. Let’s test a simple class that performs its own validation at construction time: Customer I see 3 potential candidates for testing: Testing constructor if null parameter is passed in. Testing constructor if non-null parameter is passed in. Testing method. getName() Once we test all of the above, the class will be fully tested (100% code coverage). Let’s implement those tests: g Test method names I recommend that your test method names follow a naming convention of where is optional. Let’s see how it applies to . methodNameUnderTest_givenCondition_expectedBehavior givenCondition CustomerTest consists of: ctor_givenNameIsNull_throwsException() indicates that we are testing constructor behavior ctor specifies condition when a null is passed in to the constructor givenNameIsNull name indicates that when the condition is met ( is null), we will throw an exception. Note that defines concrete exception we expect. throwsException name @Test(expected = IllegalArgumentException.class) consists of: ctor_givenNameIsValid_setsName() indicates that we are testing constructor behavior ctr specifies condition when a non-null is passed in to the constructor givenNameIsValid name indicates that when the condition is met ( is non-null), class member of our test should be set. setsName name name Customer consists of: getName_returnsName() indicates we are testing behavior of the method getName getName() indicates that a valid non-null should be returned. returnsName name Your test method names should provide a good idea about the functionality of the class under test. Also, note that each test is only a few lines of code and verifies one piece of functionality only (one being tested). unit of code Given-When-Then Let’s look at the contents of test methods themselves. Notice that all tests follow style of representing test steps. This makes each individual test a logical, easy-to-understand, consistent sequence of steps. Given-When-Then Let’s describe each of the Given-When-Then steps in more detail: — sets up a certain condition or creates the object(s) required to perform the test prior to executing the core test logic. This is effectively a pre-condition for your test. Given // GIVENString expectedName = "linda";testSubject = new Customer(expectedName); Note that is not always necessary — sometimes there is no setup is needed for a particular test or common setup is performed before each test inside method annotated with . Given @Before — this is where the action we are testing is triggered. When // WHENString actualName = testSubject.getName(); — this is where we assert that once the test action took place, the state of the application is as expected (our code under test behaves the way we expect). Then // THEN (expectedName.equals(actualName)); assertTrue There are cases when explicit is not necessary. For instance, if step is expected to throw an exception (as shown in the example above). Then When Living documentation Applying the recommendations above effectively creates concise, easy-to-read for your project. When your production code changes, the corresponding tests would change thus updating your project’s documentation. Moreover, this is an important for your entire Tech team especially for those developers and testers just joining your project. living documentation living documentation knowledge resource Conclusion I hope you see the value of applying these conventions in your unit testing. If this is new to you, it is my belief that once you try to adopt these guidelines, writing tests will suddenly become easier, faster and dare I say fun! Besides resulting in fewer bugs, you will find that future code refactoring is significantly easier as well since now your code is backed by consistent self-documenting tests. P.S. writing good tests is a marketable skill to have! ;) very