Alexander Abramovich
Alexander Abramovich

Reputation: 11438

Assertions in JavaScript

Extensively reading about various assertion frameworks in JavaScript. Is there any kind of de-facto/most common "standard" library/framework? When selecting one - which points are most worth noticing?

The (only) requirement I can think about is close-to-zero performance overhead when in production mode.

Upvotes: 6

Views: 11927

Answers (4)

SomeDude
SomeDude

Reputation: 21

I use the following to replace console.assert when it's unavailable for whatever reason.

It's definitely not a de-facto standard, and it is far from ideal, but it does satisfy your requirement that the assertion not be evaluated in production mode. Also, it shows you the expression that triggered the failed assertion, which aids debugging.

The screwy calling syntax (with a function expression) is there to create a closure, so that the assert function has access to the same variables that its caller had access to.

I suspect that this has high compile-time and run-time overhead, but I haven't attempted to verify that.

function assert(func) {
    var name;
    if (typeof(ENABLE_ASSERTIONS) !== "undefined" && !ENABLE_ASSERTIONS) {
        return;
    }
    name = arguments.callee.caller;
    name = name ? name.name : "(toplevel)";
    if (!func()) {
        throw name + ": assertion failed: " + ('' + func).replace(/function[^(]*\([^)]*\)[^{]*{[^r]*return/, '').replace(/;[ \t\n]*}[ \t\n]*$/, '');
    }
}

Using it looks like:

function testAssertSuccess() {
    var i = 1;
    assert(function() { return i === 1; });
}
function testAssertFailure() {
    var j = 1;
    assert(function() { return j === 2; });
}
ENABLE_ASSERTIONS = true;
testAssertSuccess();
testAssertFailure();

HTH!

Upvotes: 2

dsign
dsign

Reputation: 12700

Take a look to Jascree; basically it is a tool that can remove assertions with almost arbitrary logic from your code. It is handy to use as a batch processor to generate your production code or for a fastcgi-backed scripts directory that you can use when you need to test performance/profile your code.

Upvotes: 0

Mason Bryant
Mason Bryant

Reputation: 1392

Here is what I use:

When I'm working on the code I have initDevMode(); at the top of the file I'm working with, and when I'm ready to release to production, I just remove that line and all the asserts just go to an empty function.

/**
 * Log a message to console:
 *  either use jquery's console.error
 *  or a thrown exception.
 *  
 *  call initDevMode(); before use to activate
 *  use with:
 *      assert(<condition>, "message");
 *      eg: assert(1 != 1, "uh oh!");
 *  
 *  Log errors with:
 *       errorLog(message);
 *       eg: errorLog(xhr.status);
 */
assert = function(test, msg) { }
errorLog =function(msg) { }

initDevMode = function() {
    assert = function(test, msg) {
        msg = msg || "(no error message)";
        if(!test) {
            try {
                    throw Error();
                } catch(e) {
                    var foo = e;
                    var lines = e.stack.split('\n');
                    for(i in lines) {
                        if(i > 2) {
                        errorLog(msg + lines[i]);
                    }
                }
            }
        }
        throw("Assertion failed with: " + msg);
    };
    errorLog = function(msg) {
        if(typeof console.error == 'function') { 
            console.error(msg);
        } else {
            function errorLog(msg) {
                console.log("foo");
                setTimeout(function() {
                    throw new Error(msg);
                }, 0);
            }
        }
    };
}

Upvotes: 5

epascarello
epascarello

Reputation: 207511

Two possible solutions:

Have your build release script remove the Assert lines.

or

Have your build script override the Assert function so it is just an empty function. Downside to this is if you assert call has logic in it [aka assert( x > 100 , "foo" )] than that logic [x > 100] is still going to be run.

Upvotes: 7

Related Questions