lowtex
lowtex

Reputation: 737

Using Jest, how to trigger a breakpoint only when a test case fails?

Given a test case similar to this one:

test(“test”, () => {
    [1, 2, ..., 1000000].map(value => {
        expect(() => foo(value)).toThrow();
    });
})

is there a simple way to set a breakpoint (e.g. on line 3) that will only be triggered if the expect statement fails?

In other words, if one of the values somewhere in the middle of a big array is causing the test to fail, while most of the values do not trigger the exceptional condition, is there some way to set a breakpoint that will be skipped if the test passes but break if the test fails?

That would make it a lot easier to figure out why the test is failing for that value.

I am using WebStorm, so I would be satisfied with an answer for how to do it with Chrome/node, with code, or with WebStorm.

Upvotes: 2

Views: 1068

Answers (1)

Brian Adams
Brian Adams

Reputation: 45840

If you know the values at compile time then you can use test.each to create unique tests for each value which lets you see clearly which value is failing:

const tests = [[6], [7], [8]];

test.each(tests)(
  '%i should be even',
  v => {
    expect(v % 2).toBe(0);
  }
)

...which reports that two tests pass (6 and 8) and fails on 7 with a descriptive message:

● 7 should be even

expect(received).toBe(expected) // Object.is equality

Expected: 0
Received: 1

  4 |   '%i should be even',
  5 |   v => {
> 6 |     expect(v % 2).toBe(0);
    |                   ^
  7 |   }
  8 | )

  at toBe (src/code.test.js:6:19)

If the test data isn't available until runtime and the assertion is a simple one, then you can just set a conditional breakpoint on the expect line:

const generateData = count => {
  const data = [];
  for (let i = 0; i < count; i++) {
    data.push(Math.floor(Math.random() * 10) + 1);
  }
  return data;
}

test('all values are even', () => {
  generateData(1000).map(v => {
    expect(v % 2).toBe(0);  // <= set breakpoint for v % 2 !== 0
  });
})

If the test data isn't available until runtime and it would be difficult to set a conditional breakpoint then you can wrap the expect in a try / catch and put a breakpoint in the catch:

const generateData = count => {
  const data = [];
  for (let i = 0; i < count; i++) {
    data.push(Math.floor(Math.random() * 10) + 1);
  }
  return data;
}

test('all values are even', () => {
  generateData(1000).map(v => {
    try {
      expect(v % 2).toBe(0);
    }
    catch (err) {
      throw err;  // <= set your breakpoint here
    }
  });
})

expect statements work by throwing an Error if the assertion fails, so this approach simply catches and re-throws the Error but gives you a place to set a breakpoint that will get triggered for the failing expect.

Upvotes: 2

Related Questions