Champions:
- @JakobJingleheimer
Authors:
- @JakobJingleheimer
- @bridgeAR
Current: 0
Requesting: 1
This proposal may eventually split into 2 different topics:
Determining whether B is sufficiently similar (or different) to A.
Non-objects are straightforward and trivial:
'foo' === 'bar'
1 === 2
true === false
But what "similar" means is not straightforward for objects. A human considers these "equal" (but the language does not):
const a = { a: 1 };
const b = { a: 1 };
const a = [1];
const b = [1];
const a = new String('foo');
const b = new String('foo');
There is some variation in the ecosystem regarding the nuances of comparing objects.
This may be addressed by the Pattern Matching proposal.
Even more important than A vs B is the output: Merely knowing A is unexpected is almost useless when you can't see what A and B are.
examples
Annoying:
if (A !== B) throw new Error('A does not equal B');
// Error: A does not equal B
Better
if (A !== B) throw new Error(`${A} does not equal ${B}`);
// Error: 1 does not equal 2
But brittle
if (A !== B) throw new Error(`${A} does not equal ${B}`);
// Error: [object Object] does not equal [object Object]
There is potentially also an issue of representing multiple problems (such as is possible via Pattern Matching).
The vast majority of ECMAScript engineers use one of 2 forms: assert
and expect
. These come from one of ~4 libraries: chai
(20M
weekly), jasmine
(1.4M
weekly), expect
(36M
weekly), node:assert
(indeterminable). These are direct competitors, so we can assume there is no overlap and the numbers are summable: at least ~93.4M
weekly (probably significantly higher when node:assert
numbers are added).
expect
jasmine
@std/expect
by denobun:test
by bun, warning: we only referenceexpect
part not the entirebun:test
API.
It is not uncommon to include assertions within code as a means of input checking (especially input coming from an end-user):
function sum(limit, ...inputs) {
let total = 0;
for (const { valueAsNumber: val } of inputs) total += val;
assert.ok(total <= limit);
return total;
}
const expenses = sum(budget, ...form.elements.expenses);
These are then caught and surfaced to the user in a human-friendly message (such as via a "toast").
The functionality is widely used throughout the ecosystem with almost no variation. Users largely do not care about one verses the other—they care about:
- "behaves as expected"
- convenience
- how much they have to look up
The first depends on getting it right. We fortunately have decades of experience from the ecosystem to build upon.
The second two are addressed by nature of native inclusion:
- convenience: it's right there (can't get more convenient).
- how much to look up: when everyone is regularly using the same thing, it's top-of-mind so there's no lookup.
Will it be difficult: very.
Is it worth doing: yes.
Many major languages natively include a form of assertion. To name a relevant few:
- This is not a test runner (eg:
describe
,it
, etc). - This is not a test utility suite (eg:
mock
,stub
, etc).
- Investigate (and potentially decide on)
assert
vsexpect
(preliminary investigation suggestsassert
).- Possibly an amalgamation of Pattern Matching.
- Consider extensibility (public symbols?)
- Additional/replacement comparison algorithms
- Additional/replacement output handlers
- Decide on a narrow initial scope (surface-area is enormous: assertions/expectations plus output).