UNPKG

it

Version:

A testing framework for node

601 lines (510 loc) 23 kB
<!DOCTYPE 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">&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt; &lt;meta charset=&quot;utf-8&quot;&gt; &lt;title&gt;It Tests&lt;/title&gt; &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;it.css&quot;&gt; &lt;/head&gt; &lt;body&gt; &lt;div id=&quot;it&quot;&gt;&lt;/div&gt; &lt;script src=&quot;it.js&quot;&gt;&lt;/script&gt; &lt;script&gt; //optionally export assert as a global assert = it.assert; &lt;/script&gt; &lt;!--Import your scripts--&gt; &lt;script&gt; it.run(); &lt;/script&gt; &lt;/body&gt; &lt;/html&gt;</code></pre> <p>With requirejs</p> <pre class='prettyprint linenums lang-js'><code class="lang-html">&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt; &lt;meta charset=&quot;utf-8&quot;&gt; &lt;title&gt;It Tests Requirejs&lt;/title&gt; &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;it.css&quot;&gt; &lt;/head&gt; &lt;body&gt; &lt;div id=&quot;it&quot;&gt;&lt;/div&gt; &lt;script data-main=&quot;scripts/main&quot; src=&quot;scripts/require.js&quot;&gt;&lt;/script&gt; &lt;script&gt; require([ &#39;it&#39;, //require your tests ], function (it) { it.run(); }); &lt;/script&gt; &lt;/body&gt; &lt;/html&gt;</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(&quot;it&quot;), assert = require(&quot;assert&quot;); it.describe(&quot;an it test&quot;, function(it){ //the should method is a conveience over writing it(&quot;should&quot;). it.should(&quot;have a should method&quot;, function(){ assert.isFunction(it.should); }); //it can also be used as a function it(&quot;should be able to be called as a function&quot;, function(){ assert.isFunction(it); }); it.describe(&quot;#describe&quot;, 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 &gt; 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(&quot;../index&quot;), assert = require(&quot;assert&quot;); it.describe(&quot;Person&quot;, function (it) { it.should(&quot;set set name&quot;, function () { var person = new Person(&quot;bob&quot;, 1); assert.equal(person.name, &quot;bob&quot;); }); it.should(&quot;set set age&quot;, function () { var person = new Person(&quot;bob&quot;, 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(&quot;../index&quot;), assert = require(&quot;assert&quot;); it.describe(&quot;Person&quot;, function (it) { it.describe(&quot;#getOlder&quot;, function (it) { it.should(&quot;accept positive numbers&quot;, function () { var person = new Person(&quot;bob&quot;, 1); person.getOlder(2); assert.equal(person.age, 3); }); it.should(&quot;not apply negative numbers&quot;, function () { var person = new Person(&quot;bob&quot;, 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(&quot;#getOlder nested&quot;, function (it) { it.describe(&quot;with positive numbers&quot;, function (it) { it.should(&quot;work&quot;, function () { var person = new Person(&quot;bob&quot;, 1); person.getOlder(2); assert.equal(person.age, 3); }); }); it.describe(&quot;with negative numbers&quot;, function () { //uh oh wrong it it.should(&quot;not work&quot;, function () { var person = new Person(&quot;bob&quot;, 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(&quot;promise-extended&quot;); it.describe(&quot;#getOlder&quot;, function (it) { //return promise it.should(&quot;not apply negative numbers&quot;, function () { var ret = new p.promise(); var person = new Person(&quot;bob&quot;, 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(&quot;#getOlder&quot;, function (it) { //Call with next it.should(&quot;accept positive numbers&quot;, function (next) { var person = new Person(&quot;bob&quot;, 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(&quot;contexts&quot;, function(it){ it.context(function(it){ var called; it.beforeAll(function(){ called = true; }); it(&quot;should allow custom beforeAll&quot;, function(){ assert.isTrue(called); }); }); it.context(function(it){ var called it.beforeEach(function(){ called = true; }); it(&quot;should allow custom beforeEach&quot;, 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(&quot;#timeouts&quot;, function(){ it.timeout(100); //this spec will fail it.should(&quot;fail it action duration is &gt; 100&quot;, function(next){ setTimeout(function(){ next(); }, 200); }); //this spec will pass! it.should(&quot;not fail it action duration &lt; 100&quot;, 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(&quot;#timeouts&quot;, function(){ it.timeout(100); //this spec be skipped it.skip(&quot;fail it action duration is &gt; 100&quot;, function(next){ setTimeout(function(){ next(); }, 200); }); //this spec will not it(&quot;not fail it action duration &lt; 100&quot;, 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(&quot;Person&quot;, function (it) { it.suite(&quot;#getOlder&quot;, function (it) { it.test(&quot;accept positive numbers&quot;, function () { var person = new Person(&quot;bob&quot;, 1); person.getOlder(2); assert.equal(person.age, 3); }); it.test(&quot;not apply negative numbers&quot;, function () { var person = new Person(&quot;bob&quot;, 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 &quot;Person&quot;</code></pre> <p>To run the #getOlder spec</p> <pre class='prettyprint linenums lang-js'><code>it -f &quot;Person:#getOlder&quot;</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(&quot;A Person&quot;, function(it){ it.should(&quot;set set name&quot;, function () { var person = new Person(&quot;bob&quot;, 1); assert.equal(person.name, &quot;bob&quot;); }); it.should(&quot;set set age&quot;, function () { var person = new Person(&quot;bob&quot;, 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(&quot;A Person&quot;, function(it){ it.should(&quot;set name&quot;, function () { var person = new Person(&quot;bob&quot;, 1); assert.equal(person.name, &quot;bob&quot;); }); it.should(&quot;set age&quot;, function () { var person = new Person(&quot;bob&quot;, 1); assert.equal(person.age, 1); }); }); it.run(&quot;A Person:should set name&quot;);</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 &quot;then&quot;, &quot;addErrback&quot;, and &quot;addCallback&quot;)</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>