Show the faulty data when an assertion fails

Viewed 103

Often when an assertion fails I want to see what kind of data caused the issue. That's very easy with the browser's developer tools, since I can see the values on the stack. But it's harder for node.js.

Is there any simple way to show the stack trace as well as the faulty values when an assertion fails, in a short-living node.js script?

This is problem that almost every node developer faces, right? I'm surprised that there's no obvious solution then.

How do you handle this?

Example

Here is a minimal example to show the problem:

import {strict as assert} from 'assert';

function sameX(a, b){
    return a.x==b.x;
}

const a={x:1}; a.self=a;
const b={x:2}; b.self=b;

Let's say I expect sameX(a,b) to return true. If it doesn't, then I wish to print an error message, show the stack trace and show the current value of those variables.

How can I do it nicely in node?

❌ Failed attempt: extra arguments to node's assert
assert(sameX(a,b), "Objects with unexpected x", a, b);

This of course only prints:

Objects with unexpected x

since node's assert only takes two parameters.

❌ Failed attempt: stringify the objects
assert(sameX(a,b), `Objects with unexpected x ${a} ${b}`);

This prints:

Objects with unexpected x [object Object] [object Object]

I wish to see the content of a and b though.

❌ Failed attempt: JSON.stringify the objects

Something similar to:

assert(sameX(a,b), `Objects with unexpected x ${JSON.stringify(a)} ${JSON.stringify(b)}`);

Not only is a pain to type, but it may fail in some cases (like in this example where a and b have circular references).

❌ Failed attempt: console.assert
console.assert(sameX(a,b), "Objects with unexpected x", a, b);

This prints an error message I like:

Objects with unexpected x <ref *1> { x: 1, self: [Circular *1] } <ref *1> { x: 2, self: [Circular *1] }

However it doesn't throw an exception and thus doesn't even show the stack trace. I want to see the stack trace.

⚠️ Uncomfortable solution: connecting to the browser's developer tools

It's possible to debug Node using a browser's developer tools.

This works, but it's not a good option for a short-living/one-shot script that terminates in milliseconds.

Now, if there was something like a terminal that embeds the developer tools and connects them to the Node instance when one is in execution, that would be perfect. But I don't know any such terminal.

⚠️ Uncomfortable solution: custom assert function

Of course I can define my own assert function:

function assert(cond, ...msg){
    if(!cond){
        console.error("Assertion Failed!", ...msg);
        throw new Error(msg[0]);
    }
}

But I would have to copy and paste it in every project of mine and it would lack all the features of node's assert (for instance I would need to implement assert.deepEqual separately, if I need it).

A better alternative could be using an existing library. What library should I use for this though? After some searching I couldn't find any widespread library for this use case. Most assertion libraries are meant for test suites and are too heavy for production.

0 Answers
Related