最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using jest's test.each vs. looping with forEach - Stack Overflow

programmeradmin1浏览0评论

Is there a reason I would prefer one method over the other? Here are some examples:

describe('some tests', () => {
  [1, 2, 3].forEach(num => {
    test(`${num}: test`, () => {
      doSomeTestStuff(num)
    }) 
  })

  // vs.

  test.each([1, 2, 3])('%s: test', (num) => {
    doSomeTestStuff(num)
  })
})

It seems kind of difficult to read the test.each syntax, especially when you can just do native javascript iteration to achieve what seems to be the same effect. Teardown/setup still happens the same way (from what I can tell).

Is there a reason I would prefer one method over the other? Here are some examples:

describe('some tests', () => {
  [1, 2, 3].forEach(num => {
    test(`${num}: test`, () => {
      doSomeTestStuff(num)
    }) 
  })

  // vs.

  test.each([1, 2, 3])('%s: test', (num) => {
    doSomeTestStuff(num)
  })
})

It seems kind of difficult to read the test.each syntax, especially when you can just do native javascript iteration to achieve what seems to be the same effect. Teardown/setup still happens the same way (from what I can tell).

Share Improve this question asked Jul 23, 2019 at 20:15 MikeMike 6152 gold badges12 silver badges25 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 9

I would prefer the vanilla JS forEach version, because it's just JavaScript. This means:

  • You don't need to be familiar with Jest specifically, you don't need to go looking in the docs for what exactly test.each does. The test.each`table` form particularly can behave in a way that's surprising, see e.g. Jest test.each with literal table: "Not enough arguments supplied for given headings".
  • Equally it's portable between test frameworks, you can use the same approach in Mocha, Tap, etc.
  • You get proper IDE support - you need to wait for runtime to find out whether '.add($a, $b)' actually matches the properties in the objects, whereas `.add(${a}, ${b})` can be checked and autocompleted statically (and manipulated however you like, as you can interpolate arbitrary expressions).

It's not true that there's any difference in the way the tests are executed or reported. The forEach loop runs at test discovery time, and all three tests are registered. Then they're all run, separately, at execution time. You'd only see problems with failures impacting other cases if you moved the loop inside a single test case, e.g.:

describe('some bad tests', () => {
  // this an example of how not to do it
  test('num tests', () => {
    [1, 2, 3].forEach(num => {
      doSomeTestStuff(num)
    }) 
  })
})

One other thing to note with the vanilla forEach approach is that it is common, as you've shown, to inline the arrays of test cases. If you're relying on ASI, as your examples suggest you are, this sometimes means you need to prefix the array with ;:

describe('some tests', () => {
  [1, 2, 3].forEach(num => {
    test(`${num}: test`, () => {
      doSomeTestStuff(num)
    }) 
  })

  ;[4, 5, 6].forEach(num => {
    test(`${num}: test`, () => {
      doSomeTestStuff(num)
    }) 
  })
})

Without this, you'd get TypeError: Cannot read property '6' of undefined.

This is maybe a vote in Jest's favour, but if you're not going to use semicolons you do need to know when they will and won't get inserted - I'd argue it's a vote in semicolons' favour.

Great question!

On the surface it would seem like the two are basically equivalent, but there are a few reasons why you may want to use .each instead.

  • If an expectation in a forEach fails, it'll fail immediately and stop execution. This leaves you in the dark on whether the other tests in the forEach passed or failed. With .each it is basically writing a separate and distinct test for each item in your array.
  • If an expectation in a forEach fails, it's not always obvious which item in the array caused the failure. In a .each you automatically get context from the unique test name.
  • With .each you can use tagged template literals to handle multiple parameters easily, and as parameters grow the .each can be very expressive and much more readable than an array with arbitrary values.
  • Since, as I said before, .each creates a separate test for each item, the final report will make it seem like you wrote more tests than you actually have. Just a small thing that brings satisfaction when you look at the final output.

One advantage of test.each can be better tool support. I just noticed this with the VS Code plugin orta.vscode-jest.

发布评论

评论列表(0)

  1. 暂无评论