DEV Community

Bo Vandersteene
Bo Vandersteene

Posted on

Use table to validate your Unit tests with Jest

Some years ago (2017) I discovered Jest.
But what is Jest:
Jest is a delightful JavaScript Testing Framework with a focus on simplicity.
More information on jest.io

In this blog post I will not explain what jest is, but I will explain one of the features I really love: Using tables to test your code. You can build a test matrix, and then just run it through your code

Example

We have this code snippet that we want to test. As you see there can be 3 cases to test,

function calculate(a: number, b: number): number {
    if (a < b) return a + b;
    if (a === b) return a * b;
    return a - b;
}
Enter fullscreen mode Exit fullscreen mode

How we are used to do it.

With Jasmine our Jest we would write a test that looks like something bellow.

test('calculate(2, 3) should return 5', () => {
    expect(calculate(2, 3)).toBe(5);
});

test('calculate(3, 2) should return 1', () => {
    expect(calculate(3,2)).toBe(1);
});

test('calculate(3, 3) should return 9', () => {
    expect(calculate(3, 3)).toBe(9);
});
Enter fullscreen mode Exit fullscreen mode

We define the different test cases, and just write some tests for it.

But if we need to cover more test cases, then we will end up in copy pasting all these cases again and again.
Maybe we forget to update the description and finally we will end up in test cases that are no longer correct.

Add arrays that contains the test cases

Another option is to compose an array, with an array.

[[2, 3, 5] 
[3, 2, 1]
[3, 3, 9]]
Enter fullscreen mode Exit fullscreen mode

Then we write our test while looping over the result

test.each([[2, 3, 5], [3, 2, 1], [3, 3, 9]])
('calculate(%i, %i) should return $expected', (a, b, expected) => {
    expect(calculate(a, b)).toBe(expected);
});
Enter fullscreen mode Exit fullscreen mode

But again this is not maintainable and hard to read.

Also if you read the test again, you don’t know what the first value want to say, or how many values we should have.
Testing should be the documentation of your code
If we want to use the tests as the documentation of our code, then we need to make sure that the tests are readable and maintainable.
But we can use another solution in Jest, let’s look at a table

Add a table that contains the test results

But in fact our test data is a table:
| a | b | expected |
| 2 | 3 | 5 |
| 3 | 2 | 1 |
| 3 | 3 | 9 |

A table would be more readable for our code, also extending the test results would be much easier
We could write our tests as bellow

test.each`
  a    | b    | expected
  ${2} | ${3} | ${5}
  ${3} | ${2} | ${1}
  ${3} | ${3} | ${9}
`('calculate($a, $b) should return $expected', ({ a, b, expected }) => {
  expect(a + b).toBe(expected);
});
Enter fullscreen mode Exit fullscreen mode

And we could go further. We are working with typescript, so we want to add some type checking. We can define the type of our TestData just before and make more complicated test cases.

interface TestData {
  a: number, 
  b: number,
  expected: number
}
test.each`
  a    | b    | expected
  ${1} | ${1} | ${2}
  ${1} | ${2} | ${3}
  ${2} | ${1} | ${3}
`('calculate($a, $b) should return $expected', ({ a, b, expected }: TestData) => {
  expect(a + b).toBe(expected);
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)