Skip to content

Subtests cause the parent test to stop showing up as green even if it asserts. #4482

@nicholaswmin

Description

@nicholaswmin

v22.8

Creating subtests reports the parent as if they on't test anything are only a placeholder.

In the following, all the test assert something.
The output makes it appear as if only:

✔ with a name
✔ in the correct format

actually asset and have passed.


I follow the below pattern when writing tests.

If I'm asserting something deep I drill down to it contextually, step by step, to avoid duplication, because I think tests should be as concise and easy to digest as possible. it's a recommended pattern to group tests as far as I know.

The spec reporter stops showing a test as "green" when it contains subtests, even though it does assert.

This might sound pedantic but the I treat my tests as a .. spec. If I'm asserting something I want to have visual feedback in 6 months that I'm checking that title and it does pass which gives me a hint that's a valid use-case I've covered.

I routinely end up with modules with > 150 tests and the spec reporter output looks.. anemic I suppose?

Is there a reason for this?

Hope tihs makes sense.

Minimal Reproduction

import test from 'node:test'


test('Returns a parent with and its children', async t => {
  const parent = { name: 'foo', children: ['bar', 'baz'] }
  
  await t.test('is an object', async t => {
    t.assert.strictEqual(typeof parent, 'object')
    t.assert.notStrictEqual(parent, null)

    await t.test('with a name', async t => {
      t.assert.ok(Object.keys(parent).includes('name'), '"name" prop. missing')
      t.assert.notStrictEqual(parent.name.length, 0, 'name is empty ')
    })
    
    await t.test('and some children', async t => {
      t.assert.ok(Object.keys(parent).includes('children'))

      await t.test('in the correct format', t => {
        t.assert.ok(Array.isArray(parent.children), 'parent.child !== Array')
        t.assert.notStrictEqual(parent.children.length, 0, 'no children')
      })
    })
  })
})

Output

Current Output:

▶ Returns a parent with and its children
  ▶ is an object
    ✔ with a name (0.445583ms)
    ▶ and some children
      ✔ in the correct format (0.060583ms)
    ▶ and some children (0.192375ms)
  ▶ is an object (1.092125ms)
▶ Returns a parent with and its children (1.47275ms)

Expected Output

▶ Returns a parent with and its children
  ✔  is an object
    ✔ with a name (0.445583ms)
    ✔ and some children
      ✔ in the correct format (0.060583ms)
    ✔ and some children (0.192375ms)
  ✔ is an object (1.092125ms)

I would expect the current output to match something like this, without assertions in the parents, which I think is unnecessary nesting, unless there are assertions in the parent as explained above.

test('Returns a parent with and its children', async t => {
  const parent = { name: 'foo', children: ['bar', 'baz'] }
  
  await t.test('is an object', async t => {
    await t.test('with a name', async t => {
      t.assert.ok(Object.keys(parent).includes('name'), '"name" prop. missing')
      t.assert.notStrictEqual(parent.name.length, 0, 'name is empty ')
    })
    
    await t.test('and some children', async t => {
      await t.test('in the correct format', t => {
        t.assert.ok(Array.isArray(parent.children), 'parent.child !== Array')
        t.assert.notStrictEqual(parent.children.length, 0, 'no children')
      })
    })
  })
})

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions