How to Write Great Tests!
Tags: junit, java, testing, tdd
Published: 2021-02-04 23:59:01

In my  [previous post](https://pninan.hashnode.dev/junit-for-dummies-nifty-shuffle-sort-testing), I discussed a nifty sorting test. Today, I am going to teach you how to write great tests! When I write a new [JUnit](https://junit.org/junit5/) test I follow the same formula. This allows my tests to be written and read in a consistent manner. It also helps me write tests faster. I would like to share my format with you today!

## The File
The first thing I do is create a new test file/class in my project's test package and create the test method. All my tests end with `Test` so it is easy to find corresponding classes. A class named `SomeService` should have a counterpart named `SomeServiceTest`. 

Next, I make sure I give my test a good name. I personally prefer to omit the word `test` it since its redundant in a test class. The name of the test should describe what is being tested. Make you can easily differentiate similar tests.  


```
public SomeServiceTest{
    @Test
    public void sortByPopularVoteDesc() {

    }
    @Test
    public void sortByPopularVoteAsc() {

    }
}
```

## Outline
Next, I put some boilerplate inside of my method. This is the same format I use for all my tests. I set up my test, I call a function, finally, I use some sort of assertion or verify to ensure the expected results. 

```
public TestClass{
    @Test
    public void sortByPopularVote() {
      // setup
      // test
      // assert/validate
    }
}
```

Let's discuss some of these components. 

- `setup` - This is where you should prepare your code to be tested.
- `test` - This is where you should call the function being tested. This can be good to point out if you call multiple functions in your test. 
- `assert/validate` - This is where you actually use an `assert` or `validate` function to ensure the actual output matches what you expect. 

## Setup The Test
Finally, I simply fill in the blanks. If my setup is similar to **all** other tests I abstract this logic to a `@Before` function. This function gets invoked before each test. If you have a common setup between several tests, but not all of them, it is also a common practice to write a private function to encapsulate specific setup instructions. Either option makes the setup for common tests more reusable. If you have to make a change in setting up your tests you only have to make it in one place. This is very useful when a refactor breaks a certain set of tests. 

```
public TestClass{
  private List<SortableObj> expected;
  private final SortableObj first = new SortableObj();
  private final SortableObj second = new SortableObj();
  private final SortableObj third = new SortableObj();
  private final SortableObj fourth = new SortableObj();

   @Before
   public void before{
     // some decoration on objects
     // ...
     expected = Arrays.asList(first, second, third, fourth);
   }
    
    @Test
    public void sortByPopularVote() {
      // setup
      List<SortableObj> actual = Arrays.asList(fourth, third, first, second);
      // test
      Collections.sort(actual);
      // assert/validate
      assertThat(actual).isEqualTo(expected);
    }
}
```
## Testing Nomenclature
Please note the use of the variable names `expected` and `actual`. These are keywords commonly associated with writing tests and make them more easily readable. **You want the `actual` object returned from a function to match the `expected` value.**
- `expected` - This is the name of the variable for what you want your output to look like. In this example, we want a list to be in a certain order.
- `actual` - This is the name of the variable to use for the output of the function under test. It is the "actual" output to the function. 


> 
Nomenclature - The devising or choosing of names for things, especially in a science or other discipline. In the context of software, this deals with the consistent naming of API endpoints, responses, variables, functions, and documentation. 


## Conclusion
Using this format you should be able to write more consistent tests in an efficient manner. This allows you to implement more maintainable code. I hope you enjoyed this post! Check out my series on  [JUnit tests](https://hashnode.com/series/testing-your-code-ckeoueav200y5kps19v3w54pa)!

Follow me on [Twitter](https://twitter.com/ninan_phillip) if you would like to keep up to date with my latest software content!