it
Version:
A testing framework for node
601 lines (510 loc) • 23 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>it</title>
<link rel="stylesheet" href="./assets/css/bootstrap.min.css">
<link rel="stylesheet" href="./assets/css/prettify.css">
<style type="text/css">
/*.subnav-inner {*/
/*width: 100%;*/
/*height: 36px;*/
/*background-color: #EEE;*/
/*background-repeat: repeat-x;*/
/*background-image: -moz-linear-gradient(top, whiteSmoke 0%, #EEE 100%);*/
/*background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, whiteSmoke), color-stop(100%, #EEE));*/
/*background-image: -webkit-linear-gradient(top, whiteSmoke 0%, #EEE 100%);*/
/*background-image: -ms-linear-gradient(top, whiteSmoke 0%, #EEE 100%);*/
/*background-image: -o-linear-gradient(top, whiteSmoke 0%, #EEE 100%);*/
/*filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#f5f5f5', endColorstr = '#eeeeee', GradientType = 0);*/
/*background-image: linear-gradient(top, whiteSmoke 0%, #EEE 100%);*/
/*-webkit-border-radius: 4px;*/
/*-moz-border-radius: 4px;*/
/*border-radius: 4px;*/
/*}*/
/*.subnav .nav > li > a:hover {*/
/*color: black !important;*/
/*}*/
/*.subnav .nav li.dropdown .dropdown-toggle .caret,*/
/*.subnav .nav li.dropdown.open .caret {*/
/*border-top-color: #999 !important;*/
/*border-bottom-color: #999 !important;*/
/*}*/
/*.subnav-fixed {*/
/*position: fixed;*/
/*width : 90%;*/
/*margin-right: auto;*/
/*margin-left: auto;*/
/*top: 40px;*/
/*left: 0;*/
/*right: 0;*/
/*z-index: 1020;*/
/*border-color: #D5D5D5;*/
/*border-width: 0 0 1px;*/
/*-webkit-border-radius: 0;*/
/*-moz-border-radius: 0;*/
/*border-radius: 0;*/
/*-webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1);*/
/*-moz-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1);*/
/*box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1);*/
/*filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);*/
/*}*/
/*.navbar .nav .dropdown-menu {*/
/*max-height: 500px;*/
/*overflow: auto;*/
/*}*/
</style>
<style type="text/css">
body {
padding: 90px;
}
.subnav{
margin-top: 40px;
margin-right: auto;
margin-left: auto;
z-index: 1000;
}
.dropdown-menu{
max-height: 500px;
overflow-y: auto;
}
@media (max-width:979px) {
.subnav{
margin-top: auto;
}
}
</style>
<link rel="stylesheet" href="./assets/css/bootstrap-responsive.min.css">
<script type="text/javascript">
var init = (function () {
"use strict";
var processScroll = (function () {
var curr = null, prev = null;
return function (nav) {
var $win = $(window);
$('.subnav').each(function () {
var nav = $(this);
var navTop = $win.width() < 980 ? 0 : nav.offset().top - 40;
var scrollTop = $win.scrollTop();
if (scrollTop >= navTop && curr != nav) {
if(curr){
curr.removeClass('subnav-fixed')
prev = curr;
}
curr = nav;
curr.addClass('subnav-fixed')
} else if (curr == nav && scrollTop <= navTop) {
curr.removeClass('subnav-fixed');
prev.addClass('subnav-fixed');
curr = prev;
}else{
nav.removeClass('subnav-fixed');
}
});
};
})();
return function () {
window.prettyPrint && prettyPrint();
$(".collapse").collapse();
var $window = $(window);
//$(".subnav").affix ();
// fix sub nav on scroll
// processScroll();
// $(window).on('scroll', processScroll)
}
})();
</script>
</head>
<body onload="init()">
<div class="navbar navbar-fixed-top navbar-inverse">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"> </span>
</a>
<a href="./index.html" class="brand">it</a>
<div class="nav-collapse">
<ul class="nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Namespaces<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="it.html">it</a></li>
</ul>
</li>
</ul>
<ul class="nav pull-right">
<li class="divider-vertical"></li>
<li><a href="https://github.com/doug-martin/it" target="#github" class="pull-right">github</a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<a name="top"></a>
<div class="container">
<p><a href="https://travis-ci.org/doug-martin/it"><img src="https://travis-ci.org/doug-martin/it.png" alt="Build Status"></a></p>
<p><a href="http://ci.testling.com/doug-martin/it"><img src="http://ci.testling.com/doug-martin/it.png" alt="browser support"></a></p>
<h1>It</h1>
<h2>Overview</h2>
<p>It is a testing framework for node.js and the browser.</p>
<p> <strong>Features</strong></p>
<ul>
<li>Supports Promises, and the mocha <code>done(err)</code> style of async tests.</li>
<li>Browser Support</li>
<li>AMD support</li>
<li>Node.js Support</li>
<li>Proper exit codes for ci</li>
<li>Multiple reporters, including TAP for testling ci</li>
<li>Does not export global variables, you can run your tests individually with node or with the it executable.</li>
<li>Support for filtering tests.</li>
</ul>
<h2>Installation</h2>
<pre class='prettyprint linenums lang-js'><code>npm install it</code></pre>
<p>To use the it executable</p>
<pre class='prettyprint linenums lang-js'><code>npm install -g it</code></pre>
<p>In the browser</p>
<pre class='prettyprint linenums lang-js'><code class="lang-html"><!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<title>It Tests</title>
<link rel="stylesheet" type="text/css" href="it.css">
</head>
<body>
<div id="it"></div>
<script src="it.js"></script>
<script>
//optionally export assert as a global
assert = it.assert;
</script>
<!--Import your scripts-->
<script>
it.run();
</script>
</body>
</html></code></pre>
<p>With requirejs</p>
<pre class='prettyprint linenums lang-js'><code class="lang-html"><!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<title>It Tests Requirejs</title>
<link rel="stylesheet" type="text/css" href="it.css">
</head>
<body>
<div id="it"></div>
<script data-main="scripts/main" src="scripts/require.js"></script>
<script>
require([
'it',
//require your tests
], function (it) {
it.run();
});
</script>
</body>
</html></code></pre>
<h2>Usage</h2>
<h3>Getting Started</h3>
<p>The basic structure of a test in <code>it</code> looks like the following.</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">
var it = require("it"),
assert = require("assert");
it.describe("an it test", function(it){
//the should method is a conveience over writing it("should").
it.should("have a should method", function(){
assert.isFunction(it.should);
});
//it can also be used as a function
it("should be able to be called as a function", function(){
assert.isFunction(it);
});
it.describe("#describe", function(it){
//now we can write some more tests!
});
});</code></pre>
<h3>Synchronous tests</h3>
<p>Writing synchronous tests in <strong>It</strong> is extremely simple. So lets start off with an example.</p>
<p>Lets assume we have a Person Object</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">var Person = function (name, age) {
this.name = name;
this.age = age;
this.getOlder = function (years) {
if (years > 0) {
this.age = this.age + years;
}
};
};</code></pre>
<p>The first tests we could run on person could be testing the setting of name and age.</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">
var it = require("../index"),
assert = require("assert");
it.describe("Person", function (it) {
it.should("set set name", function () {
var person = new Person("bob", 1);
assert.equal(person.name, "bob");
});
it.should("set set age", function () {
var person = new Person("bob", 1);
assert.equal(person.age, 1);
});
});</code></pre>
<p>Notice we use the <strong>it</strong> passed back to the describe callback.</p>
<p>Next we could test different scenarios of Person#getOlder</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">var it = require("../index"),
assert = require("assert");
it.describe("Person", function (it) {
it.describe("#getOlder", function (it) {
it.should("accept positive numbers", function () {
var person = new Person("bob", 1);
person.getOlder(2);
assert.equal(person.age, 3);
});
it.should("not apply negative numbers", function () {
var person = new Person("bob", 1);
person.getOlder(-2);
assert.equal(person.age, 1);
});
});
});</code></pre>
<p>In this example we are describing the <strong>getOlder</strong> method and run different tests against it.
Notice the <strong>it</strong> passed back is used again.</p>
<p>You may nest tests as deep as you like as long as you remember to use the proper <strong>it</strong>. </p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">it.describe("#getOlder nested", function (it) {
it.describe("with positive numbers", function (it) {
it.should("work", function () {
var person = new Person("bob", 1);
person.getOlder(2);
assert.equal(person.age, 3);
});
});
it.describe("with negative numbers", function () {
//uh oh wrong it
it.should("not work", function () {
var person = new Person("bob", 1);
person.getOlder(-2);
assert.equal(person.age, 1);
});
});
});</code></pre>
<h3>Asynchronous tests</h3>
<p>Writing asynchronous tests in <strong>It</strong> is just as easy as writing synchronous tests.</p>
<p>Lets modify Person to make get older async</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">var Person = function (name, age) {
this.name = name;
this.age = age;
this.getOlder = function (years, next) {
setTimeout(function () {
this.age = this.age + years;
next(null, this);
}.bind(this), years * 500);
};
};</code></pre>
<p>Now that <strong>getOlder</strong> is async lets test it</p>
<p>In this example a promise is the return value. If you have used <code>comb</code>, <code>Q</code>, <code>promises-extedned</code> or any other framework that uses
<strong>Promises</strong> then this will feel pretty natural to you. The test will wait for the promise to resolve before continuing any other tests.</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">
var p = require("promise-extended");
it.describe("#getOlder", function (it) {
//return promise
it.should("not apply negative numbers", function () {
var ret = new p.promise();
var person = new Person("bob", 1);
person.getOlder(-2, function (err, person) {
assert.equal(person.age, 1);
ret.callback();
});
return ret.promise();
});
});</code></pre>
<p>In this example the should callback accepts a <code>next(err)</code> argument which is a function that should be called when the current test is done. So if next is invoked with a first argument other than null or undefined then
it is assumed that the test errored.</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">
it.describe("#getOlder", function (it) {
//Call with next
it.should("accept positive numbers", function (next) {
var person = new Person("bob", 1);
person.getOlder(2, function (err, person) {
assert.equal(person.age, 3);
next();
});
});
});</code></pre>
<h3>context</h3>
<p><code>it</code> also supports the concept of a context, which is a set of functionality that should belong to the current <code>describe</code> or <code>suite</code> tests but needs something extra like extra setup or tear down functionality.</p>
<p>In fact anything you can do withing the <code>describe</code> callback you can do in a <code>context</code>.</p>
<pre class='prettyprint linenums lang-js'><code>
it.describe("contexts", function(it){
it.context(function(it){
var called;
it.beforeAll(function(){
called = true;
});
it("should allow custom beforeAll", function(){
assert.isTrue(called);
});
});
it.context(function(it){
var called
it.beforeEach(function(){
called = true;
});
it("should allow custom beforeEach", function(){
assert.isTrue(called);
});
});
})</code></pre>
<h3>Timeouts</h3>
<p>To set a duration limit on each test within a suite use the <code>timeout(duration)</code> method.</p>
<pre class='prettyprint linenums lang-js'><code>
it.describe("#timeouts", function(){
it.timeout(100);
//this spec will fail
it.should("fail it action duration is > 100", function(next){
setTimeout(function(){
next();
}, 200);
});
//this spec will pass!
it.should("not fail it action duration < 100", function(){
assert.isTrue(true);
});
});</code></pre>
<h3>Skip</h3>
<p>If you wish to skip an action you can use the <code>skip</code> method which will put the action into a <code>pending</code> state, and not run it.</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">
it.describe("#timeouts", function(){
it.timeout(100);
//this spec be skipped
it.skip("fail it action duration is > 100", function(next){
setTimeout(function(){
next();
}, 200);
});
//this spec will not
it("not fail it action duration < 100", function(){
assert.isTrue(true);
});
});</code></pre>
<h2>Tdd</h2>
<p><code>it</code> also supports tdd style tests.</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">
it.suite("Person", function (it) {
it.suite("#getOlder", function (it) {
it.test("accept positive numbers", function () {
var person = new Person("bob", 1);
person.getOlder(2);
assert.equal(person.age, 3);
});
it.test("not apply negative numbers", function () {
var person = new Person("bob", 1);
person.getOlder(-2);
assert.equal(person.age, 1);
});
});
});</code></pre>
<h3>Running Tests</h3>
<p>To run tests there are two options the <strong>it</strong> executable </p>
<p>Options</p>
<ul>
<li>-d, --directory : The root directory of your tests</li>
<li>-f --filter : A filter to apply to run certain behaviors/suites/tests</li>
<li>-r, --reporter : The reporter to use when running the tests</li>
<li>--cov-html : create coverage output in html, if an output path is included then the file will be written to that file otherwise it will defalt to <code>./coverage.html</code></li>
<li>--reporters : Display a list of reporters that are available</li>
<li>-h, --help : Displays help.</li>
</ul>
<p>To run an entire suite</p>
<pre class='prettyprint linenums lang-js'><code>it -d ./mytests -r dotmatrix</code></pre>
<p>To run an individual test</p>
<pre class='prettyprint linenums lang-js'><code>it ./mytests/person.test.js</code></pre>
<p>Or</p>
<pre class='prettyprint linenums lang-js'><code>it -f "Person"</code></pre>
<p>To run the #getOlder spec</p>
<pre class='prettyprint linenums lang-js'><code>it -f "Person:#getOlder"</code></pre>
<p>You can alternatively run the test directly.</p>
<p><strong>Note</strong> When running tests using the <code>it.run()</code> method, <code>it</code> will not automatically exit the program on completion, therefore if you still have items like DB connections still open your program will not exit.</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">
it.describe("A Person", function(it){
it.should("set set name", function () {
var person = new Person("bob", 1);
assert.equal(person.name, "bob");
});
it.should("set set age", function () {
var person = new Person("bob", 1);
assert.equal(person.age, 1);
});
});
it.run();</code></pre>
<p>You can also filter the tests to run from within the test</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">
it.describe("A Person", function(it){
it.should("set name", function () {
var person = new Person("bob", 1);
assert.equal(person.name, "bob");
});
it.should("set age", function () {
var person = new Person("bob", 1);
assert.equal(person.age, 1);
});
});
it.run("A Person:should set name");</code></pre>
<h3>Reporters</h3>
<p><strong><code>spec</code></strong></p>
<p><img src="https://raw.github.com/doug-martin/it/master/assets/spec.png" alt="spec"></p>
<p><strong><code>dot</code></strong></p>
<p><img src="https://raw.github.com/doug-martin/it/master/assets/dot.png" alt="dot"></p>
<p><strong><code>tap</code></strong></p>
<p><img src="https://raw.github.com/doug-martin/it/master/assets/tap.png" alt="tap"></p>
<p><strong><code>doc</code></strong></p>
<p><img src="https://raw.github.com/doug-martin/it/master/assets/doc.png" alt="doc"></p>
<p><strong><code>html</code></strong></p>
<p><img src="https://raw.github.com/doug-martin/it/master/assets/browser.png" alt="html"></p>
<h3>Code Coverage</h3>
<p>If you use <a href="https://github.com/visionmedia/node-jscoverage">node-jscoverage</a> to generate coverage then by default <code>it</code> will output a coverage report. You may also output coverage to an <code>HTML</code> file by passing in the <code>--cov-html</code> flag to the executable.</p>
<p>For example out put see <a href="http://c2fo.github.com/patio/coverage.html">patio test coverage</a>.</p>
<h3>Assert extensions</h3>
<p>The following methods are added to assert for convenience</p>
<ul>
<li><code>lengthOf</code> - assert the length of an array</li>
<li><code>isTrue</code> - assert that a value is true</li>
<li><code>isFalse</code> - assert that a value is false </li>
<li><code>isRegExp</code> - assert that a value is a Regular Expression</li>
<li><code>isArray</code> - assert that a value is an Array</li>
<li><code>isHash</code> - assert that a value is a plain object</li>
<li><code>isObject</code> - assert that a value is a object</li>
<li><code>isNumber</code> - assert that a value is a Number</li>
<li><code>isDate</code> - assert that a value is a Date</li>
<li><code>isBoolean</code> - assert that a value is a Boolean</li>
<li><code>isString</code> - assert that a value is a String</li>
<li><code>isUndefined</code> - assert that a value is undefined</li>
<li><code>isUndefinedOrNull</code> - assert that a value is undefined or null</li>
<li><code>isPromiseLike</code> - assert that a value is Promise like (contains the funtions "then", "addErrback", and "addCallback")</li>
<li><code>isFunction</code> - assert that a value is a function</li>
<li><code>isNull</code> - assert that a value is null</li>
<li><code>isNotNull</code> - assert that a value is not null</li>
<li><code>instanceOf</code> - assert that a value is an instanceof a particular object</li>
<li><code>truthy</code> - assert that the value is truthy.</li>
<li><code>falsy</code> - assert that the value is falsy.</li>
</ul>
<h3>License</h3>
<p>MIT <a href="https://github.com/doug-martin/it/raw/master/LICENSE">https://github.com/doug-martin/it/raw/master/LICENSE</a></p>
<h3>Meta</h3>
<ul>
<li>Code: <code>git clone git://github.com/doug-martin/it.git</code></li>
</ul>
<hr>
Documentation generated using <a href="https://github.com/doug-martin/coddoc">coddoc</a>.
</div>
</div>
<script type="text/javascript" src="./assets/js/jquery.js"></script>
<script type="text/javascript" src="./assets/js/bootstrap.min.js"></script>
<script type="text/javascript" src="./assets/js/prettify.js"></script>
</body>
</html>