Skip to content

Commit

Permalink
Introduce an upper limit to how much actual vs. expected is diffed (#…
Browse files Browse the repository at this point in the history
…1001)

* Introduce an upper limit to how much actual vs. expected is diffed

When (accidentally) asserting on very big object graphs (like Node.js’ response objects), the actual / expected strings become hundreds of MB long.
In this case lab’s console reporter stalled for very long time while trying to create diffs for these huge strings.

* Fix lint errors and add tests for truncation

* Add test to bump coverage back to 100%

* Remove command line parameter in favor of KISS

… but keep the internal variable so we can set a very short limit for tests.
  • Loading branch information
rluba authored Dec 31, 2021
1 parent 6533396 commit 2328482
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 4 deletions.
3 changes: 2 additions & 1 deletion lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ internals.options = function () {
'lint-fix': false,
'lint-errors-threshold': 0,
'lint-warnings-threshold': 0,
'max-diff-length': 20 * 1024, // 20K should be more than most people want logged to their console. The diff algorithm becomes very slow for larger strings.
paths: ['test'],
reporter: 'console',
retries: 5,
Expand Down Expand Up @@ -463,7 +464,7 @@ internals.options = function () {
'coverage-path', 'coverage-all', 'coverage-flat', 'coverage-module', 'coverage-pattern',
'default-plan-threshold', 'dry', 'environment', 'flat', 'globals', 'grep',
'lint', 'lint-errors-threshold', 'lint-fix', 'lint-options', 'lint-warnings-threshold',
'linter', 'output', 'pattern', 'reporter', 'retries', 'seed', 'shuffle', 'silence',
'linter', 'max-diff-length', 'output', 'pattern', 'reporter', 'retries', 'seed', 'shuffle', 'silence',
'silent-skips', 'sourcemaps', 'threshold', 'timeout', 'transform', 'types', 'types-test', 'verbose'];

for (let i = 0; i < keys.length; ++i) {
Expand Down
15 changes: 13 additions & 2 deletions lib/reporters/console.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,19 @@ internals.Reporter.prototype.end = function (notebook) {
if (test.err.actual !== undefined &&
test.err.expected !== undefined) {

const actual = internals.stringify(test.err.actual);
const expected = internals.stringify(test.err.expected);
let actual = internals.stringify(test.err.actual);
let expected = internals.stringify(test.err.expected);

if (this.settings['max-diff-length'] > 0) {
const maxLen = this.settings['max-diff-length'];
if (actual.length > maxLen) {
actual = actual.substr(0, maxLen) + '[truncated]';
}

if (expected.length > maxLen) {
expected = expected.substr(0, maxLen) + '[truncated]';
}
}

output += ' ' + whiteRedBg('actual') + ' ' + blackGreenBg('expected') + '\n\n ';

Expand Down
59 changes: 58 additions & 1 deletion test/reporters.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ describe('Reporter', () => {
expect(output).to.contain(internals.colors('Leaks: \u001b[32mNo issues'));
});

it('generate a report with stable diff of actual/expected objects of a failed test', async () => {
it('generates a report with stable diff of actual/expected objects of a failed test', async () => {

const script = Lab.script();
script.experiment('test', () => {
Expand All @@ -355,6 +355,63 @@ describe('Reporter', () => {
expect(output).to.contain('Leaks: No issues');
});

it('truncates actual/expected if necessary', async () => {

const script = Lab.script();
script.experiment('test', () => {

script.test('works', () => {

expect({ a: 1 }).to.equal({ b: 1 });
});
});

const { code, output } = await Lab.report(script, { reporter: 'console', colors: false, output: false, 'max-diff-length': 8 });
expect(code).to.equal(1);
expect(output).to.contain('ab: 1[truncated]');
expect(output).to.contain('1 of 1 tests failed');
expect(output).to.contain('Test duration:');
expect(output).to.contain('Leaks: No issues');
});

it('does not truncate if max diff length is set to 0', async () => {

const script = Lab.script();
script.experiment('test', () => {

script.test('works', () => {

expect({ a: 1 }).to.equal({ b: 1 });
});
});

const { code, output } = await Lab.report(script, { reporter: 'console', colors: false, output: false, 'max-diff-length': 0 });
expect(code).to.equal(1);
expect(output).to.contain('ab: 1\n');
expect(output).to.contain('1 of 1 tests failed');
expect(output).to.contain('Test duration:');
expect(output).to.contain('Leaks: No issues');
});

it('does not truncate if diff length less than the maximum', async () => {

const script = Lab.script();
script.experiment('test', () => {

script.test('works', () => {

expect({ a: 1 }).to.equal({ b: 1 });
});
});

const { code, output } = await Lab.report(script, { reporter: 'console', colors: false, output: false, 'max-diff-length': 10 * 1024 });
expect(code).to.equal(1);
expect(output).to.not.contain('[truncated]');
expect(output).to.contain('1 of 1 tests failed');
expect(output).to.contain('Test duration:');
expect(output).to.contain('Leaks: No issues');
});

it('counts "todo" tests as skipped', async () => {

const script = Lab.script();
Expand Down

0 comments on commit 2328482

Please sign in to comment.