Skip to content

Commit

Permalink
test_runner: expose reporter for use in run api
Browse files Browse the repository at this point in the history
PR-URL: #47238
Fixes: #47231
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
  • Loading branch information
atlowChemi committed Mar 28, 2023
1 parent 67200dc commit 29d7aec
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 1 deletion.
28 changes: 27 additions & 1 deletion doc/api/test.md
Expand Up @@ -520,6 +520,10 @@ test('spies on an object method', (t) => {
added:
- v19.6.0
- v18.15.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/47238
description: Reporters are now exposed at `node:test/reporters`.
-->

The `node:test` module supports passing [`--test-reporter`][]
Expand All @@ -546,6 +550,16 @@ Node.js, and should not be relied on programmatically. If programmatic access
to the test runner's output is required, use the events emitted by the
{TestsStream}.

The reporters are available via the `node:test/reporters` module:

```mjs
import { tap, spec, dot } from 'node:test/reporters';
```

```cjs
const { tap, spec, dot } = require('node:test/reporters');
```

### Custom reporters

[`--test-reporter`][] can be used to specify a path to custom reporter.
Expand Down Expand Up @@ -739,8 +753,20 @@ added:
**Default:** `undefined`.
* Returns: {TestsStream}

```js
```mjs
import { tap } from 'node:test/reporters';
import process from 'node:process';

run({ files: [path.resolve('./tests/test.js')] })
.compose(tap)
.pipe(process.stdout);
```

```cjs
const { tap } = require('node:test/reporters');

run({ files: [path.resolve('./tests/test.js')] })
.compose(tap)
.pipe(process.stdout);
```

Expand Down
38 changes: 38 additions & 0 deletions lib/test/reporters.js
@@ -0,0 +1,38 @@
'use strict';

const { ObjectDefineProperties } = primordials;

let dot;
let spec;
let tap;

ObjectDefineProperties(module.exports, {
__proto__: null,
dot: {
__proto__: null,
configurable: true,
enumerable: true,
get() {
dot ??= require('internal/test_runner/reporter/dot');
return dot;
},
},
spec: {
__proto__: null,
configurable: true,
enumerable: true,
get() {
spec ??= require('internal/test_runner/reporter/spec');
return spec;
},
},
tap: {
__proto__: null,
configurable: true,
enumerable: true,
get() {
tap ??= require('internal/test_runner/reporter/tap');
return tap;
},
},

This comment has been minimized.

Copy link
@sahidshaikh23

sahidshaikh23 Jul 31, 2023

Proposed Change: Add New Test Reporter Module

Description:
This change adds a new test reporter module called "json" to the internal/test_runner/reporter directory. The reporter will generate test results in JSON format, providing a structured and machine-readable output for test runs.

Motivation:
The addition of the "json" test reporter module aims to enhance the test reporting capabilities of the Node.js test runner. JSON format is widely used and makes it easier to integrate test results with various tools and systems.

How This Works:
The change modifies the test_runner_reporters.js file to include a new property "json" in the module.exports object. The lazy initialization pattern (??=) is used to load the reporter module only when it's accessed for the first time, improving performance.

Example Usage:
Once this change is merged, users can use the new "json" reporter by specifying it as the reporter in the Node.js test runner. For example:

});
36 changes: 36 additions & 0 deletions test/parallel/test-runner-run.mjs
Expand Up @@ -2,6 +2,7 @@ import * as common from '../common/index.mjs';
import * as fixtures from '../common/fixtures.mjs';
import { join } from 'node:path';
import { describe, it, run } from 'node:test';
import { dot, spec, tap } from 'node:test/reporters';
import assert from 'node:assert';

const testFixtures = fixtures.path('test-runner');
Expand Down Expand Up @@ -65,4 +66,39 @@ describe('require(\'node:test\').run', { concurrency: true }, () => {
code: 'ERR_INVALID_ARG_TYPE'
}));
});

it('should be piped with dot', async () => {
const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(dot).toArray();
assert.deepStrictEqual(result, [
'.',
'\n',
]);
});

it('should be piped with spec', async () => {
const specReporter = new spec();
const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(specReporter).toArray();
const stringResults = result.map((bfr) => bfr.toString());
assert.match(stringResults[0], /this should pass/);
assert.match(stringResults[1], /tests 1/);
assert.match(stringResults[1], /pass 1/);
});

it('should be piped with tap', async () => {
const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(tap).toArray();
assert.strictEqual(result.length, 13);
assert.strictEqual(result[0], 'TAP version 13\n');
assert.strictEqual(result[1], '# Subtest: this should pass\n');
assert.strictEqual(result[2], 'ok 1 - this should pass\n');
assert.match(result[3], /duration_ms: \d+\.?\d*/);
assert.strictEqual(result[4], '1..1\n');
assert.strictEqual(result[5], '# tests 1\n');
assert.strictEqual(result[6], '# suites 0\n');
assert.strictEqual(result[7], '# pass 1\n');
assert.strictEqual(result[8], '# fail 0\n');
assert.strictEqual(result[9], '# cancelled 0\n');
assert.strictEqual(result[10], '# skipped 0\n');
assert.strictEqual(result[11], '# todo 0\n');
assert.match(result[12], /# duration_ms \d+\.?\d*/);
});
});

0 comments on commit 29d7aec

Please sign in to comment.