Функция юнит-тестирования


У меня есть функция JavaScript, которая была написана немного спонтанно и я не совсем уверен, как идти об оптимизации и улучшения.

Это в основном реализация проекта юнит-тестирования/1.1 спецификация.

// Runs the object as a test. The async paramater is an optional function
// To be passed in if the test is to be run async.
// notRoot is an internal paramater
var run = function(object, async, notRoot) {
    // if its the root call then cache the async func for us in _pushTests
    if (!notRoot) {
        func = async;
    }
    // tests to run
    var tests = [];
    // Assert constructor to be used is either on the object or from assert
    var Assert = object.Assert || assert.Assert;
    var failures = 0;
    // Push the tests to the tests array
    _pushTests(object, tests);
    var len = tests.length;
    // function that runs the test
    var testRunner;
    // If async Do I have to document it? It's full of the hacks.
    if (async) {
        // results object stores the calls to pass/fail/error
        var results = {};
        results.passes = [];
        results.fails = [];
        results.errors = [];
        // tests passed in the test object
        var testsPassed = 0;
        testRunner = function(val, key) {
            // Local assert object
            var _assert = new Assert;
            // Forward the mute property to the assert
            if (object.mute === true) {
                _assert.mute = true;    
            }
            // cache pass, fail & error
            var _pass = _assert.pass;
            var _fail = _assert.fail;
            var _error = _assert.error;
            // Wrap pass. Push the pass massge to the results object
            _assert.pass = function(message) {
                _pass.apply(_assert, arguments);
                results.passes.push(message);
                // If an assert passed after done then throw an error in 
                // assert.error
                if (doneCalled) {
                    _assert.error(new Error(
                        "assertion passed after done was called" + 
                        "for test : " + key + " and message was : " +
                        message
                    ));
                }
            }
            // Wrap fail. Push the fail message to the results object
            _assert.fail = function(message) {
                _fail.apply(_assert, arguments);
                results.failures.push(message);
                // Throw an error if assertion failed after done has been
                // called
                if (doneCalled) {
                    _assert.error(new Error(
                        "assertion failed after done was called" + 
                        "for test : " + key + " and message was : " +
                        message
                    ));
                }
            }
            // Wrap error. Log calls to error
            _assert.error = function(error) {
                _error.apply(_assert, arguments);
                results.errors.push(error);
            }
            // Done has not been called
            var doneCalled = false;
            var done = function() {
                // If its not been called then set it to be called
                if (!doneCalled) {
                    doneCalled = true;
                    // Increment the number of tests that have passed
                    // If we have passed all then call the async function
                    // with the results
                    if (++testsPassed === len) {
                        async(results, object.name);    
                    };
                } else {
                    // Done has already been called thrown an error
                    _assert.error(new Error(
                        "done already called for test : " + key
                    ));
                }
            };
            // Try running the test function.
            try {
                val(_assert, done);    
            } catch(e) {
                // If a failure occurs log it when its an AssertionError
                if (e instanceof assert.AssertionError) {
                    console.log("failed : " + e.message);
                } else {
                    // and throw if its another error
                    _assert.error(e);
                }
                failures++;
            }
        };
    } else {
        // the test runner takes the test function as a paramater
        testRunner = function(val) {
            // create a local assert
            var _assert = new Assert;
            // If we want to mute it then pass mute to the assert
            if (object.mute === true) {
                _assert.mute = true;    
            }
            // Try the test
            try {
                val(_assert);
            } catch(e) {
                // If it throws an assertion error then log it
                if (e instanceof assert.AssertionError) {
                    console.log("failed : " + e.message);
                } else {
                    // Other error thrown so pass it to assert.error
                    _assert.error(e);    
                }
                failures++;
            }
        };
    }
    // For each test run it.
    _.each(tests, testRunner);
    // If the object had a name and was not async then print a message
    // saying we've finishe
    if (object.name && !async) {
        var string = "Completed " + len + 
            " tests. Finished : " + object.name +
            " with " + failures + " tests failing";
        console.log(string);        
    }
    // Return the count of failures (Kind of useless for async).
    return failures;
};

Дополнительные сведения полный файл можно найти здесь. Он также опирается на утверждать объекта, который описан здесь.

Есть некоторые (ограниченные) модульные тесты, и они могут быть запущены в браузере здесь.

Скажите, пожалуйста, если нужна дополнительная информация.

Я собирался написать некоторые должном высоком уровне документации о том, как использовать его, потому что на CommonJS спецификаций является немного расплывчатым. Я буду редактировать, когда это сделано.



538
20
задан 19 февраля 2011 в 05:02 Источник Поделиться
Комментарии