Jest (a little bit more)

We’ve covered rudimentary use of Jest as part of React testing, also in a stand alone, now let’s look a little more in depth at common testing requirements.

Unit Test

We write tests using Jest like this

test('Some test description', () => {
});

Note: there are various aliases such as “it”, “fit”, “xit” or “xtest” that can be used in place of “test”.

Obviously the “Some test description” text should be something meaningful, i.e. what is being tested, any specific inputs and what’s the expectation. Ofcourse how much or how little you write as a description is upto the developer. I tend to write what method is being tested, with any special conditions and expected outcome simply because when the tests run I get a good set of information on what’s working and what’s not, however this is down to the developer’s specific tastes.

We can group tests together within a describe function which may allow you to reduce the verbosity of your test descriptions as well as logically group tests, for example

describe('fetch component', () => {
    test("missing URL, expect empty response", () => {
    });

    test("missing invalid, expect error", () => {
    });
});

Note: there are a couple of aliases such as “fdescribe” and “xdescribe” which can be used in place of “describe”.

The output of the Jest test runner would be something like this

fetch component
   √ missing URL
   √ missing invalid

Timeout

The test function also accepts a third argument which can be a timeout (specified in milliseconds). The default timeout is 5 seconds. So for example

test("missing URL, expect empty response", () => {
}, 100);

Paramterized tests

Jest supports paramterized tests using the each function, so for example

test.each`
   input         | output
   ${1}          | ${10} 
   ${5}          | ${50} 
   ${10}         | ${100} 
  `("should return $output when $input is used", ({input, output}) => {
   expect(input * 10).toBe(output);
});

Using a “table”-like layout of data, the first row made up of column names which map to the input(s) and output along with subsequent rows of inputs and outputs to match against delimited using the pipe | operator.

You can also pass in arrays instead of a table structure, i.e.

test.each([[1, 10], [5, 50], [10, 100]])
   (`should return %i when %i is used`, (input, output) => {
   expect(input * 10).toBe(output);
});

We can also supply parameters using the each function of describe meaning we can pass the same parameters through multiple tests. Here’s an example of the above two way of passing parameterized data, but using describe

describe.each`
  input         | output
  ${1}          | ${10} 
  ${5}          | ${50} 
  ${10}         | ${100} 
  `("multiplication with input $input, output $output", ({input, output}) => {

  test("should match", () => {
    expect(input * 10).toBe(output);
  });
})  

describe.each([[1, 10], [5, 50], [10, 100]])
(`multiplication %i, %i`, (input, output) => {

  test("should match", () => {
    expect(input * 10).toBe(output);
  });
});

Only run these tests

During development we might wish to turn off tests whilst we work on a specific set of tests, we can use the only function on either describe or test to basically just run those tests with only specified. For example the following syntax (followed by the normal describe and test parameters)

describe.only 
describe.only.each
test.only
test.only.each

Skipping tests

We can run only certain tests and the opposite (i.e. run all tests except these), skipping tests using the skip

describe.skip
describe.skip.each
test.skip
test.skip.each

Todo

With @types/jest version 24 the todo function was added to test. With this we might have ideas for our tests and want to quickly create stub methods, so we would write

test.todo('multiple number test');

No function should be supplied to a todo test and the Jest tester runner will show the test as a “todo” test within it’s output.

Lifecycle functions

Most unit testing frameworks include the ability to carry out some process before or after a test, for example setting up a test and cleanup, Jest is no different – including beforeAll, beforeEach, afterAll and afterEach functions.

As the names suggest, beforeAll and afterAll are invoked before the tests start and after the tests all complete, respectively. As you’ll have worked out beforeEach and afterEach will be invoked before and after each test is run, respectively.

All life cycle functions accept a function to invoke and an optional timeout.

Expectations

Obviously these previously mentioned tests will all succeed unless we include expectations/assertions. Jest includes the expect function which you’ll often pass the value your system under test returned (or set) along with a function such as toBe which is what you expect the value to be, for using our previous multiplication test

expect(input * 10).toBe(output);

There’s a whole host of functions around expect listed here “Expect”.