Unit testing: #1 - Test one behaviour at a time.
Tags: javascript, testing, unittest
Published: 2022-06-19 10:57:57

In the previous part of the blog series on unit testing, I mentioned the why part and summarised some points to be taken care of while writing unit tests. I am going to elaborate on these points one by one. To explain I will be using examples using [Jest](https://jestjs.io/), a JavaScript testing framework. 

## Test a single behaviour

Tests are written in blocks and each block should ideally test for a single behaviour. Let us look at an example. 

```
function sum(a, b) {
  return a + b;
}
module.exports = sum;
```
```
const sum =  require("../src/sum");

test("should give sum of two numbers", () => {
  expect(sum("1", "2")).toBe(3); //assertion 1
  expect(sum(1,2)).toBe(3); //assertion 2
});
```

There are 2 assertions above, one is testing the sum of two numbers of type string and the second is testing the sum of two numbers of type number. 


![1 Test failed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kbdt0lwjsvfe82kbrtcx.png)

The above test block fails in its entirety and shows as 1 test failed. As assertion 1 failed, it blocked the rest of the line of code from executing. When there are hundreds of tests it is not easy to see from the test results, which of the assertions has failed and which of them would have passed. You would have to scroll through the long logs to know which line of the test has an error and which part of the code needs fixing.

 To save our time in future, we are going to separate the test as below.

```
test("should give sum of two numbers of type string", () => {
  expect(sum("1", "2")).toBe(3);
});

test("should give sum of two numbers of type numbers", () => {
  expect(sum(1,2)).toBe(3);
});
```
Now if I run the test using the jest command, I will receive the test results as follows

![1 Test failed 1 Test passed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0bhbebaxnmkpxre227b6.png)

From the above you can see that 1 test failed whereas the other test passed, it is easy to focus on the failed behaviour. 

Now let's go and fix the code. 

```
function sum(a,b){
  return Number(a) + Number(b);
}
```
The test passes and how beautiful is to behold those green ticks. 

![Both Tests passed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yugf231eola39hhf7b4j.png)

The tests should not end there, keep adding more data points to test the code. For example

```
test("should return number if one of them is undefined", () => {
  expect(sum(undefined,2)).toBe(2);
});
```

The above test fails and gives the below test results

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yx0yd04qo631832fwzqe.png)

You will keep on modifying the code until it passes all the required behaviour for different data inputs. As a result, you will have a code of high quality and whenever the requirement of behaviour changes in future, start with a test and then go on fixing it. 

What we did in the last step was similar to TDD (Test Driven Development) - the red, green and refactor method. Write a failing test, then write the minimum code to make it pass; then make it better by refactoring the code.  Although in TDD we could further divide the steps of code by first returning a hardcoded number 3, then testing with another set of number inputs which would make the earlier tests fail, and the cycle continues.