Ava: Test.each: easily test similar scenarios

Created on 25 Oct 2018  Â·  6Comments  Â·  Source: avajs/ava

I propose adding a function similar to jest's test.each. In my opinion it only needs to support arrays, not tables. This would make it much easier to test similar cases, and would be more readable and concise than a manual for loop or forEach.

Most helpful comment

You could achieve that with a for loop, which I find this easier to understand:

for (const [expression, result] of [
  ['2 + 2', 4],
  ['2 * 3', 6],
  ['2 - 2', 0],
  ['4 / 2', 2],
  ['2 * 16', 32],
  ['2 + 8 * 2', 18]
]) {
  test(`${expression} = ${result}`, macro, expression, result)
}

All 6 comments

I think our macro functions cover this use case: https://github.com/avajs/ava#test-macros

(I'm closing this issue for housekeeping purposes, but let's keep the conversation going.)

Those help, but a simple helper function makes them even quicker to use:

import test from 'ava'

function macro(t, input, expected) {
  t.is(eval(input), expected)
}

test('2 + 2 = 4 (macro)', macro, '2 + 2', 4)
test('2 * 3 = 6 (macro)', macro, '2 * 3', 6)

function each1(scenarios, name, testFn) {
  scenarios.forEach(params => {
    let testName = name
    params.forEach(param => {
      // TODO: proper interpolation
      testName = testName.replace('%s', param)
    })
    test(testName, testFn, ...params)
  })
}

each1([['2 + 2', 4], ['2 * 3', 6]], '%s = %s (each1)', macro)

function each2(scenarios) {
  return function(name, macro) {
    scenarios.forEach(params => {
      let testName = name
      params.forEach(param => {
        // TODO: proper interpolation
        testName = testName.replace('%s', param)
      })
      test(testName, macro, ...params)
    })
  }
}

each2([['2 + 2', 4], ['2 * 3', 6]])('%s = %s (each2)', macro)

output:

yarn run v1.13.0
$ /home/noah/Documents/HTML/ava-test/node_modules/.bin/ava -v

  ✔ 2 + 2 = 4 (macro)
  ✔ 2 * 3 = 6 (macro)
  ✔ 2 + 2 = 4 (each1)
  ✔ 2 * 3 = 6 (each1)
  ✔ 2 + 2 = 4 (each2)
  ✔ 2 * 3 = 6 (each2)

  6 tests passed

Done in 0.82s.

What do you think about including one of these?

It might need some updated to accept different types of args.

Could you elaborate what you're proposing with each1 and each2?

The idea would be to add one of these functions as test.each. The goal is to make it really easy to test similar scenarios, so you aren't using array.forEach, writing multiple tests, or something similar.

Without test.each:

test('2 + 2 = 4', macro, '2 + 2', 4)
test('2 * 3 = 6', macro, '2 * 3', 6)
test('2 - 2 = 0', macro, '2 - 2', 0)
test('4 / 2 = 2', macro, '4 / 2', 2)
test('2 * 16 = 32', macro, '2 * 16', 32)
test('2 + 8 * 2 = 18', macro, '2 + 8 * 2', 18)

with test.each:

test.each(
  ['2 + 2', 4],
  ['2 * 3', 6],
  ['2 - 2', 0],
  ['4 / 2', 2],
  ['2 * 16', 32],
  ['2 + 8 * 2', 18]
)('%s = %s', macro)

You could achieve that with a for loop, which I find this easier to understand:

for (const [expression, result] of [
  ['2 + 2', 4],
  ['2 * 3', 6],
  ['2 - 2', 0],
  ['4 / 2', 2],
  ['2 * 16', 32],
  ['2 + 8 * 2', 18]
]) {
  test(`${expression} = ${result}`, macro, expression, result)
}
Was this page helpful?
0 / 5 - 0 ratings