Skip to content

A tiny utility, that helps to find cause of seemingly random failures in your code.

License

Notifications You must be signed in to change notification settings

valango/assert-fine

Repository files navigation

assert-fine

Build Status Code coverage

A lightweight wrapper making assertion testing much easier.

Why and How

  1. After assertion failure, we'll have stack trace, showing the execution context. But sometimes we need a detailed view of dynamic data, even interactive debugging, before AssertionError is thrown.
    The beforeThrow() hook makes it easy.
  2. Including dynamic data to assertion messages comes at cost of additional code and performance penalty.
    The overridden ok(), fail() and ifError() functions feature lazy formatting in a backwards-compatible manner.
  3. Front-end assertion is supported too, with minimalistic API of (AssertionError, fail, ifError, ok) by default. So you can use same code in both back- and front-end (via a bundler).
  4. The use() function lets you switch the assertion engine programmatically, w/o re-loading any modules.

When loaded, the assert-fine package object instance transparently wraps around the environment-specific assertion engine like the Node.js assert

The #1 functionality was actually proposed, but rejected Node.js feature request #5312.

Installation

npm install -S assert-fine
or
yarn add assert-fine

Usage

const assert = require('assert-fine')

assert.beforeThrow(() => {  //  This call is optional.
  return false              //  The breakpoint place.
})

//  Somewhere in your code
assert(value === expected, 'assert(%o)', value, someFunction, ...argsForFunction)

assert.equal(value, expected, 'Bang!')  //  Not affected by `assert-fine`.

In the example above, the someFunction will be called, and the message is formatted only when the assertion fails.

Package exports (API)

Default export

Default export equals the ok() function.

function beforeThrow([callback: function|false])

Sets, resets or just queries the global callback function.

The callback will be called right before the assertion error is thrown. It's main purpose is to provide debugger breakpoint. Returns function | undefined the global callback value so far.
Throws TypeError if supplied argument is not function nor falsy.

function fail( [failure], ...args )

Replaces its Node.js counterpart, featuring the lazy formatting and invoking the callback set via beforeThrow().

Arguments:
failure: Error | function - if a function supplied, it is treated as Error constructor, and error instance is created with message property composed of args; if Error instance is supplied, the string composed of args is appended to its message.
args: any - optional arguments. If the first one is a string, it will be supplied to util.format or to its front-end substitute. If any of the args is a function, it will be called with the rest opf arguments supplying its return value to format().

function ifError( value, ...args )

Replaces its Node.js counterpart, featuring the lazy formatting and invoking the callback set via beforeThrow(). Arguments:
value: any
args: any - optional arguments, working exactly as those of fail().

function ok( value, ...args )

Replaces its Node.js counterpart, featuring the lazy formatting and invoking the callback set via beforeThrow(). Arguments:
value: any
args: any- optional arguments, working exactly as those of fail().

function use( engine )

Wraps the assertion engine, putting it into use. This function is called internally upon loading the package, with Node.js built-in assert package or with its own substitute, when loaded via a bundler (browserify, webpack, rollup or similar.)
You might need this function when using something like assert package for front-end.

This function does not modify the supplied engine instance in any way, and
it does not alter the exported ( beforeThrow, fail, ifError, ok, use ) values either.

All other properties of the engine argument will be assigned to the already exported API.

property strict?: function()

Is present only if the assertion engine in use has such property (see Node.js docs), it will be mirrored to the package object instance. For subtle details, see the source code.

Other properties

Any properties of the assertion engine, not shadowed by the API described above, will be directly assigned to package object instance.

Advanced topics

Changing package settings

Calls to beforeThrow() or use() anywhere in your code affect the state assert-fine instance kept in require.cache or alike. It is preferable to make these calls from the application boot module, before executing any other code.

Switching the assertion engine

If you need something special in place of the default engine, do something like this:

import engine from 'assert'         //  A npm package for front-end applications.
import assert from 'assert-fine'

assert.use(engine)  //  Should be executed _before_ any possible assertion call.

Technically, it is possible to switch engines at any moment.

The global callback function

This function, if set via beforeThrow(), should be kept as simple as possible. It's typical use is just to provide a code line for debugger breakpoint.

If the callback itself throws an error, it will be stored in assertion instance's extra property and its message will be appended to the assertion message using '[EXTRA]:' prefix.

The callback receives two arguments:
error: Error - the instance that will be thrown;
args: any[] - the args from the call of fail(), ifError() or ok().

Acknowledgements

assert npm package - I borrowed quite some pieces of code from there - thanks a lot, folks!

debug npm package - inspecting its source code helped me to fix the disastrous bug (issue #1) of this package - thanks again!

About

A tiny utility, that helps to find cause of seemingly random failures in your code.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published