Permalink
Browse files

Added errors to teardown callback

* Added lots of documentation
* Added an okay set of tests
* Fixed a bug related to unflushed contexts
* Improved the README
* Fixed an issue with the test command in
the package.json
  • Loading branch information...
1 parent 44fc356 commit 0d8c3e6dcba21a6d7d2a522f44d84b4fc17e62f9 Siddharth Mahendraker committed Nov 22, 2011
Showing with 122 additions and 30 deletions.
  1. +22 −14 README.md
  2. +1 −2 TODO.md
  3. +11 −4 bin/srunner.js
  4. +68 −7 lib/stest.js
  5. +5 −3 package.json
  6. +15 −0 test/test-stest.js
View
@@ -1,4 +1,8 @@
-# stest - Sane async tests
+# stest - A Sane Async Testing Framework
+
+Frustrated with other testing frameworks which
+kinda sucked at handling async, I decided to make
+stest.
# Installation:
@@ -26,8 +30,8 @@ A very simple test:
other_event: function(hello){
assert.equal("Hello!", hello);
},
- teardown: function(){
-
+ teardown: function(errors){
+ if(errors.length > 0) assert.ok(0);
}
}).run();
@@ -38,23 +42,28 @@ corresponding functions associated with the name of the
event you emitted.
The `setup` and `teardown` functions are given to you
-to setup your test case.
+to setup your test case, and optionally, to perform
+a teardown.
-The `opts` argument allows you to specify a `timeout`.
-If all async calls are not called before that time, then
-the `stest` will give you a heads up.
+The `opts` argument allows you to specify a `timeout`
+in miliseconds. If all async calls are not called
+before that time, then the `stest` will give you a heads up.
-Tests can be run en masse like this:
+See the source for more details and documentation.
- srunner -r test/test-*.js
+# Running Tests:
-Or like this:
+Tests can be run en masse using `srunner`:
- node test.js
+ srunner -r test/test-.*\.js
-If you prefer not to use `srunner`.
+To run tests silently, run `srunner` with the `-s`
+option. If you prefer not to use `srunner`, you can
+still run tests like this:
-# License
+ node test.js
+
+# License:
(The MIT License)
@@ -77,4 +86,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-
View
@@ -1,4 +1,3 @@
# TODO
-* Add tests for `stest`
-
+* Add code coverage
View
@@ -9,14 +9,21 @@ var path = require("path"),
.demand(["r"])
.argv;
-//options
+/* srunner args
+ *
+ * -r: regexp of files to test
+ * -s: silent
+ *
+ */
+
var silent = argv.s ? argv.s : false;
var r = path.join(process.cwd(), argv.r);
var info = function(buffer, colr){
- var string = buffer.toString();
- if(!silent)
+ if(!silent){
+ var string = buffer.toString();
process.stdout.write(color(string, colr));
+ }
}
var dir = path.dirname(r);
@@ -39,6 +46,6 @@ if(!filtered.length){
filtered.forEach(function(file){
cp.exec("node "+dir+"/"+file, function(err, stdout, stderr){
if(err) throw err;
- if(!silent) info(stdout);
+ info(stdout);
});
});
View
@@ -10,10 +10,10 @@ var events = require("events"),
function stest(){
- this._queue = [];
this.ctx = {};
this.promise = new events.EventEmitter();
-
+ this._queue = [];
+
this._addTime = function(func){
var now = Date.now();
func();
@@ -26,8 +26,10 @@ function stest(){
c = "green";
if(!errors.length)
+ // check
result = "\u2713";
else{
+ // cross
result = "\u2717";
c = "red";
}
@@ -51,6 +53,60 @@ function stest(){
* @param {Object} opts
* @param {Object} test
*
+ * The name will be displayed upon output.
+ *
+ * The opts object looks like this:
+ *
+ * var opts = { timeout: 1000 }
+ *
+ * After the number of miliseconds specified by
+ * the timeout parameter, stest will throw an
+ * error. If you provide 0, or do not provide a
+ * timeout value, the default timeout is 250
+ * miliseconds.
+ *
+ * The test object looks something like this:
+ *
+ * {
+ * setup: function(promise){
+ * // emit events
+ * promise.emit("event_1", 42);
+ * },
+ * event_1: function(num){
+ * // catch events
+ * assert.deepEqual(42, num);
+ * },
+ * teardown: function(errors){
+ * // (optional)
+ * // the errors object can
+ * // be modified if you intend to
+ * // create errors
+ * }
+ * }
+ *
+ * The setup key is required, all other keys and
+ * functions are optional. Errors in the teardown
+ * function have two extra properties; an event
+ * property indicating the event that wasn't fired,
+ * and a type, indicating weather the error was
+ * generated by stest or not. stest errors have a
+ * type equal to "stest". For example:
+ *
+ * teardown: function(errors){
+ * // created two intentional errors earlier
+ * if (errors.length > 2) assert.ok(0);
+ * }
+ *
+ * This method can also be chained to include
+ * multiple cases, like so:
+ *
+ * stest.addCase(...,{
+ * ...
+ * })
+ * .addCase(..., {
+ * ...
+ * }).run();
+ *
* @api public
*/
@@ -63,14 +119,18 @@ stest.prototype.addCase = function(name, opts, test){
/*
* Runs the test cases synchronously
*
+ * All output is written to stdout.
+ *
* @api public
*/
stest.prototype.run = function(){
+ // clear context
+ this.ctx = {};
var self = this;
- this._queue.forEach(function(tcase, index, array){
+ this._queue.forEach(function(tcase){
var test = tcase.test;
var opts = tcase.opts;
@@ -84,7 +144,7 @@ stest.prototype.run = function(){
// to record error
var errors = [];
- // delete the setup and teardown keys
+ // d elete the setup and teardown keys
delete test["setup"];
if(test["teardown"]) delete test["teardown"];
@@ -96,6 +156,7 @@ stest.prototype.run = function(){
try{
test[event].apply(self.ctx, args);
}catch(e){
+ e.event = "event";
errors.push(e);
}
});
@@ -114,13 +175,14 @@ stest.prototype.run = function(){
if(ears > 0){
var e = new Error("The '"+event+"' event never fired.");
e.type = "stest";
+ e.event = event;
errors.push(e);
self.promise.removeAllListeners(event);
}
});
-
+
// user teardown
- totalTime += self._addTime(function(){ teardown.apply(self.ctx,[]); });
+ totalTime += self._addTime(function(){ teardown.apply(self.ctx,[errors]); });
//give a report
self._report(name, errors, totalTime);
}, (opts.timeout > 0 ? opts.timeout : 250));
@@ -129,4 +191,3 @@ stest.prototype.run = function(){
// Exports
module.exports = new stest();
-
View
@@ -1,20 +1,22 @@
{
"author": "Siddharth Mahendraker <siddharth_mahen@me.com>",
"name": "stest",
- "description": "Sane event driven async testing.",
+ "description": "A sane event driven async testing framework.",
"version": "0.0.2",
"keywords": [
"async",
"test",
- "event"
+ "event",
+ "testing",
+ "framework"
],
"repository": {
"type": "git",
"url": "git://github.com/siddMahen/stest.git"
},
"main": "lib/stest.js",
"scripts": {
- "test": "srunner -r test/test-.*.js"
+ "test": "srunner -r test/test-.*\.js"
},
"bin": {
"srunner": "/bin/srunner.js"
View
@@ -1,6 +1,7 @@
var assert = require("assert"),
stest = require("../lib/stest");
+// defaults to 250 ms
var opts = { timeout: 0 };
stest.addCase("stest - basic tests", opts, {
@@ -25,4 +26,18 @@ stest.addCase("stest - basic tests", opts, {
assert.deepEqual("hello", data);
}
})
+.addCase("stest - advanced tests", opts, {
+ setup: function(promise){
+ setTimeout(function(){
+ promise.emit("ok");
+ }, 1000);
+ },
+ ok: function(){},
+ teardown: function(errors){
+ assert.ok(errors);
+ var err = errors.pop();
+ assert.deepEqual("ok", err.event);
+ assert.deepEqual("stest", err.type);
+ }
+})
.run();

0 comments on commit 0d8c3e6

Please sign in to comment.