Coder Social home page Coder Social logo

vows's Introduction

vows

vows is a testing framework for NodeJS.

License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Example

var vows = require('vows');

// vows does not pollute the assert module namespace by default

var assert = vows.assert;

vows
  .describe("My first vows test")
  .addBatch({
    'When we open a file': {
      topic: function() {
        fs.open("/tmp/fakefile", "w", this.callback);
      },
      'it works': function(err, fd) {
        assert.ifError(err);
        assert.isNumber(fd);        
      },
      teardown: function(fd) {
        fs.close(fd, this.callback);
      }
      'and we write to the file': {
        topic: function(fd) {
          fs.write(fd, "My dog has fleas\n", this.callback);
        },
        'it works': function(err, written, buffer) {
          assert.ifError(err);
          assert.greater(written, 0);
          assert.isString(buffer);        
        }
      }
    }
  })
  .run();

Introduction

Requiring

You require the module like any other module.

Assert macros

vows provides its own suite of assert macros. To use them, you should use the assert property from the vows module, like so:

var vows = require('vows');
var assert = vows.assert;

Data structures

The basic way to use tests is to build really large hierarchical objects with a particular well-defined form.

Batch

For vows, the core concept is the test batch. A batch is an object that consists of the following:

  • A topic function that generates values to be tested

  • One or more test functions, which accept the results of the topic and use assert macros to validate the results

  • Zero or more sub-batches

  • An optional teardown function that cleans up any values generated by the topic

A batch can be either synchronous or asynchronous. For a synchronous batch, the topic function just returns a value, and the test functions measure that value:

let batch = {
  "We get the answer":  {
    topic() {
      return 6 * 7;
    },
    "it equals 42": (err, answer) => {
      assert.ifError(err);
      assert.equal(answer, 42);
    }
  }
};

For an asynchronous batch, the topic returns its results through the callback property of this. vows knows that the callback will be used because the result returned by the topic function is undefined.

let batch = {
  "When we get the answer asynchronously":  {
    topic() {
      setImmediate(() => {
        this.callback(null, 6 * 7);
      });
      return undefined;
    },
    "it equals 42": (err, answer) => {
      assert.ifError(err);
      assert.equal(answer, 42);
    }
  }
};

Alternately, a topic can return a Promise. vows will resolve the returned Promise and call tests with the same (err, results) format as with other types of call.

let batch = {
  "When we get the answer":  {
    topic() {
      return new Promise((resolve, reject) => {
        fs.open("/tmp/testfile", "w", (err, fd) => {
          if (err) {
            reject(err);
          } else {
            resolve(fd);
          }
        })
      });
    },
    "it equals 42": (err, fd) => {
      assert.ifError(err);
      assert.isNumber(fd);
    }
  }
};

Note that all test functions receive at least an err argument, and then one or more arguments. Synchronous batches can only have one test argument; asynchronous batches can have a lot.

For backwards compatibility, it's possible to call this.callback synchronously in your topic. vows will simply call setImmediate to call the callback later. But that is a tricky and confusing way to write your tests, and you should probably avoid it.

A batch can also have sub-batches. These are just properties of the batch that are also batch objects, with their own topic, tests, sub-batches, teardown, etc. The argument to the topic will be the results of the parent batch, in reverse order up the hierarchy.

let batch = {
  "When we get the answer":  {
    topic() {
      return 6 * 7;
    },
    "it equals 42": (err, answer) => {
      assert.ifError(err);
      assert.isNumber(answer);
      assert.equal(answer, 42);
    },
    "and we ask a couple of questions": {
      topic(answer) {
        return [
          "What is six times seven?",
          "How many roads must a person walk down?"
        ];
      },
      "they look plausible": (err, questions) => {
        assert.ifError(err);
        assert.isString(question[0]);
        assert.equal(question[0][question[0].length - 1], '?');
        assert.isString(question[1]);
        assert.equal(question[1][question[1].length - 1], '?');
      },
      "and we compare the answer and the question": {
        topic(questions, answer) {
          setImmediate(() => {
            this.callback(null, questions[0], questions[1], answer);
          });
          return undefined;
        },
        "they match up well": (err, question0, question1, answer) => {
          assert.ifError(err);
          // NB: you need to implement isAnswerTo yourself
          assert(isAnswerTo(answer, question0));
          assert(isAnswerTo(answer, question1));
        }
      }
    }
  }
};

Note that if a batch's topic returns more than one value to its callback, they will be provided in order for any sub-batches' topic, but hierarchically in reverse order. This may be a little confusing.

Note also that if an error occurs, in either the topic or the tests, the sub-batches will not be run.

The teardown method is called after all the tests and sub-batches have been run. So, the order is something like this:

  • topic
  • tests
  • sub-batches (if there are no errors)
  • teardown

The teardown gets the non-error results of the topic as arguments. It's useful for cleaning up things that the topic made a mess of.

batch = {
  'When we open a file': {
    topic: function() {
      fs.open("/tmp/fakefile", "w", this.callback);
    },
    'it works': function(err, fd) {
      assert.ifError(err);
      assert.isNumber(fd);
    },
    teardown: function(fd) {
      fs.close(fd, this.callback);
    }
  }
};

teardown functions can also be synchronous or asynchronous, or they can return a Promise. However, the results are ignored.

let batch = {
  "When we get the answer":  {
    topic() {
      return new Promise((resolve, reject) => {
        fs.open("/tmp/testfile", "w", (err, fd) => {
          if (err) {
            reject(err);
          } else {
            resolve(fd);
          }
        })
      });
    },
    "it equals 42": (err, fd) => {
      assert.ifError(err);
      assert.isNumber(fd);
    },
    teardown(fd) {
      return new Promise((resolve, reject) => {
        if (typeof(fd) != 'number') {
          reject(new Error("File descriptor is not a number"));
        } else {
          fs.close(fd, (err) => {
            if (err) {
              reject(err);
            } else {
              resolve();
            }
          })
        }
      });
    }
  }
};

Note that the teardown will be called regardless of whether errors happened or not, so it's a good idea to check the arguments to make sure they're valid.

Teardowns are called as soon as the batch finishes; this is different from how vows.js works, but it is better.

If you're using a version of node that can handle async/await syntax, (>= 7.10.1), you can use async functions in your topics and teardowns, which can make your aysnchronous test code about as lovely and compact as can be.

const fs = require('fs');
const util = require('util');

// util.promisify is available in node > 8.0.0

const open = util.promisify(fs.open);
const close = util.promisify(fs.close);

let batch = {
  "When we get the answer":  {
    topic: async function () {
      return await open("/tmp/testfile", "w");
    },
    "it equals 42": (err, fd) => {
      assert.ifError(err);
      assert.isNumber(fd);
    },
    teardown: async function (fd) {
      return await close(fd);
    }
  }
};

Suite

Batches are organized into suites. You create a suite with the describe method of vows.

const vows = require('vows');

let suite = vows.describe('A new suite');

You can then add one or more batches to the suite using the addBatch method.

suite.addBatch(batch1);
suite.addBatch(batch2);
suite.addBatch(batch3);

Finally, you have two options to actually run the test suite. The first is the aptly-named run() method, which runs all the tests and reports the results to stdout. You can then run the script through node and you'll run all your tests.

Alternately, you can use the export() method, passing the current module as an argument. This will change the exports property of the module to be the run() method of the suite. In other words, the module will now export a single function that runs the suite.

The vows command-line tool can be used to run all your test modules that use export().

./node_modules/.bin/vows test/*.js

All the suite methods are chainable. The typical way to actually use this library, then, is to require vows, use the describe method to create a suite, use addBatch to add one or more batches, and then use export(module) or more rarely run() to run the suite.

const fs = require('fs');
const vows = require('vows');
let assert = vows.assert;

vows.describe('Input/output tests')
  .addBatch({
    'When we open a file': {
      topic: function() {
        fs.open("/tmp/fakefile", "w", this.callback);
      },
      'it works': function(err, fd) {
        assert.ifError(err);
        assert.isNumber(fd);
      },
      teardown: function(fd) {
        fs.close(fd, this.callback);
      }
    }
  })
  .export(module);

CoffeeScript

CoffeeScript is a nice pre-processor for JavaScript. If you write your test scripts in CoffeeScript, it's totally OK to run them with the vows command-line tool, as-is.

./node_modules/.bin/vows test/*.js test/*.coffee

vows uses the CoffeeScript package to load the test modules automatically.

Debugging

Test-driven development means roughly that write your tests first, then write the implementations, then keep running the tests till they work.

vows doesn't necessarily do a fantastic job at this, but it's a little better, and it's definitely a goal. vows uses the debug library to spoot out debug info to stderr at run time. This can be very useful for looking at how the vows module is running, and figuring out where errors are happening.

To use it, define the DEBUG environment variable when running your tests:

DEBUG=vows:* ./node_modules/.bin/vows mytest.js

Watch this space for more help in doing TDD with vows.

Compatibility

This 1.x version is incompatible with previous 0.x versions of vows in a few small ways.

  • vows 0.x will check the arity of test methods and call the method different ways based on that arity. With vows 1.x, tests will always take an error argument and then zero or more result arguments. This should help preserve your sanity and make you write more robust tests.

  • vows 0.x will automatically pollute the namespace of the assert module. vows 1.x makes you use a property instead.

  • vows 0.x handle all teardowns at the same time, without waiting for sub-batch teardowns to finish. vows 1.x handles teardowns when the batch is finished, so you can do things like deleting created files in your sub-batch teardowns, and deleting their directory in your main batch teardown, and things will just work right.

  • vows 0.x treat a Promise returned from the topic just like any other results. So test functions will receive the Promise as a results argument. vows 1.x will resolve the Promise and pass the results to the test instead. So, if your tests expect to receive a Promise passed synchronously, you should change that.

  • vows 1.x does not pass this.context to the topic.

  • vows 1.x does not support many of the undocumented features of vows 0.x, including vows.prepare(), beforeSuite(), afterSuite(), and vows.options.

  • vows 1.x only provides a single, default reporter.

  • vows 1.x does not support command-line control of verbosity (-v or -s).

  • vows 1.x does not support the -m or -r command-line flags.

  • vows 0.x automatically runs any tests in the test or spec directory. vows 1.x requires that you specify the tests you want to run.

  • vows 1.x does not support the -i (isolate) command-line flag.

assert

The exposed assert module-ish object has a number of useful methods for doing tests.

The module exposes all the methods of the built-in assert module. It also has the following utility methods. Each will do a check and if the check fails, will throw a new AssertionError with either the message argument as its message, or a standard message for that macro.

assert.epsilon(eps, actual, expected, message)

Checks that the number actual is within eps from expected.

assert.match(actual, expected, message)

Checks that actual matches the regular expression expected. Note that actual will be coerced to a string if it is not one already.

assert.matches is a synonym.

assert.isTrue(actual, message)

Checks that actual is true (not just truthy; true).

assert.isFalse(actual, message)

Checks that actual is false (not just falsy; false).

assert.isZero(actual, message)

Checks that actual is 0.

assert.isNotZero(actual, message)

Checks that actual is not 0.

assert.greater(actual, expected, message)

Checks that actual is strictly greater than expected.

assert.lesser(actual, expected, message)

Checks that actual is strictly lesser than expected.

assert.inDelta(actual, expected, delta, message)

Checks that actual is less than delta away from expected. It's a lot like assert.epsilon().

assert.include(actual, expected, message)

Checks that actual contains expected. assert.includes is a synonym.

assert.notInclude(actual, expected, message)

Checks that actual does not contain expected. assert.notIncludes is a synonym.

assert.isEmpty(actual, message)

Checks that actual is empty (an empty array or an object with no properties).

assert.isNotEmpty(actual, message)

Checks that actual is not empty.

assert.isArray(actual, message)

Checks that actual is an array.

assert.isObject(actual, message)

Checks that actual is an object.

assert.isNumber(actual, message)

Checks that actual is a number.

assert.isBoolean(actual, message)

Checks that actual is a boolean (true or false).

assert.isNaN(actual, message)

Checks that actual is NaN.

assert.isNull(actual, message)

Checks that actual is null.

assert.isNotNull(actual, message)

Checks that actual is not null.

assert.isUndefined(actual, message)

Checks that actual is undefined.

assert.isDefined(actual, message)

Checks that actual is not undefined.

assert.isString(actual, message)

Checks that actual is a string.

assert.isFunction(actual, message)

Checks that actual is a function.

assert.typeOf(actual, expected, message)

Checks that actual is of type expected.

assert.instanceOf(actual, expected, message)

Checks that actual is an object and an instance of expected.

vows's People

Contributors

evanp avatar strugee avatar trott avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vows's Issues

Async topic isn't passed to vows in topic-less subcontexts

Here's a test case. Notice that only the marked vow is not honored, the other ones are just there for comparison.

var vows = require('vows'),
    assert = require('assert');

vows.describe('Vows bug').addBatch({
    'Sync 42': {
        topic: 42,
        'equals 42': function (topic) {
            assert.equal(topic, 42);
        },
        'has the property that': {
            'it is equal to 42': function (topic) {
                assert.equal(topic, 42);
            }
        }
    },
    'Async 42': {
        topic: function () {
            var callback = this.callback;
            process.nextTick(function () {
                callback(null, 42);
            });
        },
        'equals 42': function (topic) {
            assert.equal(topic, 42);
        },
        'has the property that': {
            'it is equal to 42': function (topic) { // <-- This vow fails, topic is undefined!?
                assert.equal(topic, 42);
            }
        },
        'plus 1': {
            topic: function (parentTopic) {
                return parentTopic + 1;
            },
            'equals 43': function (topic) {
                assert.equal(topic, 43);
            }
        }
    }
})['export'](module);

Support JUnit XML reporter

It would be nice to add JUnit XML reporter to Vows, so that Vows could be used in Continuous Integration.

Convention for naming spec files?

vows --watch assumes a convention for naming spec files, but generally it loads all the files it finds in spec/test, not just those with test-/spec- in their name.

If it filtered and only loaded files that follow the convention (when not giving explicit file names), it would be easier to work with vows and have unrelated JavaScript files in the spec directory.

My test suite includes JS files that should not be required (I load them separately), but are part of the data used for testing.

Error in assert.isNull()

When running assert.isNull on an Error object, it swiftly returns a TypeError:

> assert.isNull(new Error());
<error: TypeError: Cannot call method 'match' of undefined>
    at [object Context]:1:8
    at Interface.<anonymous> (repl.js:141:22)
    at Interface.emit (events.js:42:17)
    ...

options.error not honored for suite

suite.js has this.options = {error: true} in the constructor, ignoring the value you have specified in vows.options.error.

This error feature I would almost consider broken, as not every callback takes an error as first argument...

for example http.get({/**/, this.callback);
will blow up because it only has 1 argument, the response, making you have to wrap this.callback to pass null instead...

So I did

var vows = require('vows');
vows.options.error = false;

but noticed it still did not work due to Suite ignoring your setting.

The options.error stuff really needs to be removed from context.js line 20~ event emitter.

Have it only apply to an ACTUAL event emitter if it triggers error, not on callbacks.

What is passed to this.callback should be exactly what is passed to your test cases.

Circular references in JSON

I am using vows to test an endpoint and when it tries converting the response (i think) I am getting this error:

TypeError: Converting circular structure to JSON
    at Object.stringify (native)
    at Object.report    (/Users/ryanfairchild/.node_libraries/.npm/vows/0.4.6/package/lib/vows/reporters/json.js:7:19)
at Object.report (/usr/local/bin/vows:155:27)
at [object Object].report (/Users/ryanfairchild/.node_libraries/.npm/vows/0.4.6/package/lib/vows/suite.js:215:37)
at output (/Users/ryanfairchild/.node_libraries/.npm/vows/0.4.6/package/lib/vows.js:114:21)
at EventEmitter.<anonymous> (/Users/ryanfairchild/.node_libraries/.npm/vows/0.4.6/package/lib/vows.js:80:13)
at EventEmitter.emit (events:25:26)
at /Users/ryanfairchild/.node_libraries/.npm/vows/0.4.6/package/lib/vows/context.js:28:47
at Request.<anonymous> (/Users/ryanfairchild/.node_libraries/.npm/vows/0.4.6/package/lib/vows/context.js:42:29)
at Request.emit (events:25:26)`

I used vows -v --json test/* on my file.

The test code works outside of vows without problem. I am using my own rolled oauth library but like I said here it works outside of vows.

My test case without vows:

var oauth = require('oauth-client'),
        sys = require('sys'),
        vows = require('vows');     
var consumer = oauth.createConsumer('key','secret');
var signature = oauth.createHmac(consumer);
var client = oauth.createClient(80,'api.simplegeo.com');    
var req = client.request('GET','/0.1/nearby/address/28.541479,-81.369891.json',null,null,signature);
req.addListener('response',function(response) {
sys.p(response)
var data = ''
response.addListener('data', function(chunk) {
    data += chunk
})
response.addListener('end',function() {
    sys.p(JSON.parse(data))
})
});

req.end();

This is the batch:

var oauth = require('oauth-client'),
    sys = require('sys'),
    vows = require('vows');


exports.endpoints = vows.describe('endpoints')
.addBatch({
    'requesting a reverse geocode lookup': {
        topic: function() {
            var consumer = oauth.createConsumer('key','secret');
            var signature = oauth.createHmac(consumer);
            var client = oauth.createClient(80,'api.simplegeo.com');
            var req = client.request('GET','/0.1/nearby/address/28.541479,-81.369891.json',null,null,signature);
            req.end();
            req.addListener('response',this.callback);
        },
        'should return a status 200': function(response) {
                sys.p(response)
                assert.equal(1,1)
        }
    }
});

To test this you would need oauth-client from npm, and a simple geo account to get a valid key and secret

vows folder/* should only include files in the directory

I have a folder containing my tests, but inside this folder there is also a few folders - ie a lib-folder for my macros and a folder for fixtures. So right now I have to use
vows test/*.js instead of just vows, because it complains that it can't load the module "test/lib", when it tries to require() it.

So when passed multiple files (ie, from using *, or using folder discovery), it should (imho) only try to use files that are actually files, and not try to use folders as well.

Typo in http://vowsjs.org/ documentation

'when peeled synchronously': {
topic: function (banana) {
return banana.peelSync();
},
'returns a PeeledBanana': function (result) {
assert.instanceOf (result, PeeledBanana);
}
}
'when peeled asynchronously': {
topic: function (banana) {
banana.peel(this.callback);
},
'results in a PeeledBanana': function (err, result) {
assert.instanceOf (result, PeeledBanana);
}
}

this is missing a comma before 'when peeled *asyc....

Module not found

I just installed vows with npm, however, when I try to run vows, e.g. 'vows --help', I get the following error:

module:252
    throw new Error("Cannot find module '" + request + "'");
          ^
Error: Cannot find module '/usr/local/lib/node/.npm/vows/0.4.6/package/bin/vows'
at loadModule (module:252:15)
at require (module:378:12)
at Object.<anonymous> (/usr/local/bin/vows:5:18)
at Module._compile (module:427:23)
at Module._loadScriptSync (module:437:8)
at Module.loadSync (module:310:10)
at Object.runMain (module:491:22)
at node.js:253:10

assert.isNaN doesn't actually check for the literal value NaN

The javascript isNaN function doesn't actually check for NaN because it does type conversion. The reliable way to check is to use the fact that NaN !== NaN so assert.isNaN becomes

assert.isNaN = function (actual, message) {
if (actual === actual) {
assert.fail(actual, 'NaN', message || "expected {actual} to be NaN", "isNaN", assert.isNaN);
}
};

(Cosmetics) Show filenames with dots properly

A small change to the regex in assert/error.js should work:

-        source = this.stack.match(/([a-zA-Z0-9_-]+\.js)(:\d+):\d+/);
+        source = this.stack.match(/([a-zA-Z0-9_\.-]+\.js)(:\d+):\d+/);

Emit event when done running tests

I'm testing HTTP requests against a Web server. I start it up from the first test that runs, and need to shut it down when the last test finishes. Tried using topic/teardown and reference counting, but that didn't pan out very well.

Hooking into console.result works great. Would be nice to have that as a supported API.

Don't run every exported object

I have a lot of common helper functions that I keep in spec/helpers.js and export out. That works well when running individual files, but when running all files in the spec directory, Vows complains that the exported objects can't be run.

Would be great if it only attempted to run batches, not every exported object.

Diagnosing non-exit case.

I'm currently seeing one of my vows files refusing to exit (i.e. it just sits and waits after OK is reported). In my experience, this can be due to some test waiting for a callback and the callback not being delivered...

Is there some way to diagnose this? Is there some debug/verbosity mode that will show me what's in the wait queue that's not being fulfilled? If not, is there some way to add this?

Option to prevent sub-topic "waterfalling"

Right now there are quite a few tests of mine that depend upon other tests, when the parent topics fail I wish there was a means to prevent the child topics from being run (just declare them as skipped somehow) so I could see more relevant information than tests failing because an expected test before them failed.

Newbie bug/issue with example from website.

When I run the first example on the http://vowsjs.org/ page, I get the following error:

chris@cyan:~/test$ vows division-by-zero-test.js

Could not find any tests to run.
???
\u2713 OK ? 3 honored (0.003s)

(the output does not paste well - ? is >> and \u2713 is a tick)

What have I done wrong, or is it a bug? I have installed by npm, I'm using NodeJS 0.2.4 and vows 0.5.2.

Thanks.

Chris.

Add --no-color option

It would be nice to have a --no-option and/or a smart color support detection in vows. For example when I use vows inside eclipse all escape characters around colored texts are displayed as ugly squares symbols...

Thanks

Add support for adding batches via optional parameters in describe()

The addBatch provides some exception clarity to what is happening in the test suite, but I would love to be able to use it optionally. Instead of having to call describe("foo").addBatch({}), it would be nice to be able to do describe("foo", {}). This requires slight mental parsing to shift to this style, but it really allows the tests to enter center stage and focus on what they're doing with only one call from Vows being present.

EventEmitter.once no longer exists?

node 0.3.5 is giving me this error when running a test on a class containing an EventEmitter:

./src/com/nilbog/utility/role/EventEmitter.js:47
this.getEventEmitter().once(event, listener);
^
TypeError: Object # has no method 'once'
at [object Object]. (./src/com/nilbog/utility/role/EventEmitter.js:47:27)
at [object Object].once (/usr/local/lib/node/.npm/joose/3.17.0/package/lib/Task/Joose/Core.js:777:32)
at [object Object]. (./src/com/nilbog/game/engine/action/ActionTimeline.js:142:11)
at [object Object].addAction (/usr/local/lib/node/.npm/joose/3.17.0/package/lib/Task/Joose/Core.js:777:32)
at Object. (/Users/jmhnilbog/workspaces/Nilbog/nilbog/tests/ActionTimeline.js:27:10)
at run (/usr/local/lib/node/.npm/vows/0.5.1/package/lib/vows/suite.js:126:31)
at EventEmitter. (/usr/local/lib/node/.npm/vows/0.5.1/package/lib/vows/suite.js:197:40)
at EventEmitter.emit (events:43:20)
at Array.0 (/usr/local/lib/node/.npm/vows/0.5.1/package/lib/vows/suite.js:148:58)
at EventEmitter._tickCallback (node.js:53:20)

Dumping the keys of EventEmitter to the console gives me only:

·_events
emit
addListener
on
removeListener
removeAllListeners
listeners
addVow

Assert namespace shouldn't be modified and stack trace is not very readable

Vows is a nice test library, but it should not modify the 'assert' namespace. Further the stack trace that is printed when an assert fails is much LESS READABLE than the built in node one:

node.js:116
throw e; // process.nextTick error, or 'error' event on first tick
^
<error: TypeError: Cannot call method 'match' of undefined>
at Object. (REMOVED)
at run (/usr/local/lib/node/.npm/vows/0.5.3/package/lib/vows/suite.js:128:31)
at EventEmitter. (/usr/local/lib/node/.npm/vows/0.5.3/package/lib/vows/suite.js:200:40)
at EventEmitter.emit (events.js:59:20)
at Array. (/usr/local/lib/node/.npm/vows/0.5.3/package/lib/vows/suite.js:150:58)
at EventEmitter._tickCallback (node.js:108:26)

Versus the one from node:

node.js:116
throw e; // process.nextTick error, or 'error' event on first tick
^
AssertionError: true == false
at Object. (Removed)
at Module._compile (module.js:287:26)
at Object..js (module.js:293:10)
at Module.load (module.js:219:31)
at Function._load (module.js:186:10)
at Array. (module.js:307:10)
at EventEmitter._tickCallback (node.js:108:26)


Node's stack trace clearly says assertion failed, whereas the vows stack trace is complaining that you cannot call 'match' on undefined.

Pass priority to nested topic for this.callback.

I was looking for a better way to write an async test for this scenario: I have an event "next" that is raised after start() is called but is also subsequently raised after each call to next(). The first case (verifying it's raised by start() is easy with vows), but the second test (verifying the event is raised by next() is complicated):

http://github.com/indexzero/http-agent/blob/master/test/http-agent-test.js#L157

It would be easier and cleaner imo if I could pass priority for this.callback to a nested topic instead of having to do the hack above.

Run tests for test files with "_" in filename.

At the root of my project I have a test folder with some test files in it. Before the latest upgrades I could run.

vows

From my project root and it would run all the tests in the folder. Now it does:

Could not find any tests to run.

Let me know if there is any other info you need.

CoffeeScript support under 0.3.x

Node 0.3.x no longer supports registerExtension, need to use new extensions method to support CoffeeScript.

Copied from CoffeeScript and added to bin/vows (line 15):

try {
  var coffee = require('coffee-script');
  if (require.extensions) {
    require.extensions[".coffee"] = function(module, filename) {
      content = coffee.compile(fs.readFileSync(filename, "utf8"));
      module._compile(content, filename);
    }
  } else
    require.registerExtension('.coffee', function (content) { return coffee.compile(content) });
  fileExt     = /\.(js|coffee)$/;
  specFileExt = /-(test|spec)\.(js|coffee)$/;
} catch (_) {
  fileExt     = /\.js$/;
  specFileExt = /-(test|spec)\.js$/;
}

I tested this on Node 0.3.7 with CoffeeScript 1.0.1, but didn't get a chance to test with Node 0.2.6.

how is --watch mode supposed to work?

When editing a file that is watched by vows, nothing seems to happen when saving it. I can even trigger a syntax error, but the dot thingy just keeps moving.

Am I missing something? (OSX, v0.1.98-5-g02da5ed)

use of export throws an error in JSLint

export is a reserved word in JS so doing vows.describe( ... ).addBatch( ... ).export(module) is throwing an error (not even a warning) in jsLint. so jsLint stops testing (the jerks!). Just a heads up, not sure if we could rename to exports or give us jsLinters a non-erronous name or if there is a workaround that I'm not aware of I'd love to hear it.

Wish to have more assertion available to show my intention

I can not agree more with this description in the doc:

It’s always best to use the more specific assertion functions when testing a value, you’ll get much better error reporting, because your intention is clearer.

But, to do so, I notice some very basic assertion are missing:

example:

No assert.isDefined(), so I must write assert.true(goo[9] !== undefined)

No assert.notEmpty(), so I must write assert.true([1,2] !== [])

Any chance to see these assertion added ?

Or, is there already a nice way to simulate them ? (better than the one I use right now)

The 'isGreaterThan' and 'isLessThan' would also be very welcome addition ;-)

Watch mode doesn't re-evaluate files?

When I use watch mode, it seems to be running my tests again when I update the file, but not actually reloading the file before running the test again. How is this supposed to work?

Here's how I'm able to reproduce the "bug" on OSX 10.6.5:

  1. Create an empty directory, and then create a subdirectory with one file ./test/test.js with the following code:
var vows = require('vows'),
    assert = require('assert');

// Create a Test Suite
vows.describe('test').addBatch({
    'just for kicks': {
        '1 equals 1': function () {
            assert.equal(1, 1);
        }
    }
}).export(module);
  1. Start vows -w -v, verify the line vows watcher watching [ 'test/test.js' ]

  2. Edit test.js to say assert.equal(1, 2); and save. Vows will recognize the change and display "1 Broken"

  3. Edit test.js back to assert.equal(1, 1); and save. Vows will recognize the change, but will still display "1 Broken"!

EventEmitters with multiple arguments doesn't work with this.callback

Hi,

I might just not have understood the correct usage of this.callback - but shouldn't the attached Vow work as expected? The code does what the Vows says, but the Vow fails because it doesn't transfer all arguments returned from the EventEmitter

var vows = require('vows'),
    assert = require('assert'),
    events = require('events');

myEmitter = new events.EventEmitter();

vows.describe('myEmitter').addBatch({
    'Any EventEmitter': {
        topic: function() {
            myEmitter.on('myEvent', this.callback);
            myEmitter.emit('myEvent', 'arg1', 'arg2', 'arg3');
        },
        'Can have multiple arguments': function() {
            assert.strictEqual( arguments.length > 1, true );
        },
        'Returns the first argument': function( a1, _, _ ) {
            assert.equal( a1, 'arg1' );
        },
        'Returns the second argument': function( _, a2, _ ) {
            assert.equal( a2, 'arg2' );
        },
        'Returns the third argument': function( _, _, a3 ) {
            assert.equal( a3, 'arg3' );
        }
    }
}).export(module);

Instead it fails (First vow fails with "An unexpected error was caught: arg1", which can be resolved by adding arguments to the function testing - don't know why this is)

The 3rd and 4th vow fails because a2 and a3 are "undefined" - they arent transfered from this.callback to the vow..
My guess, after a very brief look through the code, is that this is the reason why:
https://github.com/cloudhead/vows/blob/master/lib/vows/suite.js#L156-164
Shouldn't it pass all of arguments onto the contexts topics?

Or have I just completely misunderstood how this.callback is supposed to work, and should construct my EventEmitters differently so they are all return a (status, data)-tuple to use them with Vows - even though my use-case is currently supported by Node?

Tests hang when the topic inherits from EventEmitter

Sometimes you want to test an object that inherits from EventEmitter. In this case, if you return said testable object as the topic, then the code hangs if the EventEmitter subclass instance that I'm testing doesn't emit "success" or "error." I'll submit a pull request to fix this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.