table of contents

writing tests

Testling tests are just javascript. When you upload a test to testling, it gets browserified, fully-instrumented to support stack traces, and then run inside all the browsers requested.

an example test

var test = require('testling');
test('the test name', function (t) {
    t.equal(2 + 2, 4);
    t.createWindow('substack.net', function (win, $) {
        t.equal(win.document.title, 'The Universe of Discord');
This example test defines a new test with the name "the test name". The test asserts that 2 + 2 = 4, logs the window.navigator.appName, then navigates to substack.net with t.createWindow(). When substack.net loads, the test checks that the title is what is expected. Finally the test ends when t.end() fires.
In IE9, our test prints:
robot : ~ $ curl -sSNT test.js \
Bundling....  done

iexplore/9.0        2/2  100 % ok
  Log: Microsoft Internet Explorer

total               2/2  100 % ok
robot : ~ $ 
Check out the running tests section for more info on running these tests.

test methods

The testling API is heavily inspired by node's assert module and node-tap.
To load the test harness, use require() to load the testling module:
var test = require('testling')
Then just call test() with a name and test callback.

test(testName, cb)

Create a new test with an optional name and test callback.
test('the test name', function (t) { /* ... */ })
The test callback will get a new test object with the methods listed below. When your test is finished, make sure to call t.end().


Get the browser name and version being used. This object looks like:

test control


Plan to run n tests. If more or less tests are run, an error is generated.


Finish a test. No more assertions should fire once this method has been called.

t.createWindow(opts, cb)

Load the web page at opts.url. If opts.url starts with a file://, . or a /, load an HTML file from the multi-file upload.
Once the window object has loaded, cb(win, $) fires with the window object win and a jquery object, $, which is bound to the window object.
Returns the new window object, which may not be fully loaded yet.
If opts.url is a string, treat it as opts.url.
You can also set opts.method, opts.headers, and opts.data in order to make POST and other fancy requests.
Once the window has loaded you can submit forms and click links for the most part. HTTPS doesn't work yet.
To get XMLHttpRequests (AJAX) to work, try using absolute URLs when making requests. Instead of xhr.open("POST", "/", true), try xhr.open("POST", window.location.href, true).

t.submitForm(form, opts={}, cb)

Submit the HTML form object provided.
This method is deprecated. Now you can just form.submit()!
opts and cb(win, $) work mostly the same as in t.createWindow().
However if the form.method is "POST", opts.data is specified, and opts.headers['transfer-encoding'] isn't "chunked", then opts.headers['content-length'] with be automatically sent with the correct length for the form data.

test assertions

t.ok(value, [message])

Assert that value has a truthy (non-falsy) value.

t.notOk(value, [message])

Assert that value has a falsy value.


Generate an error.

t.equal(x, y, [message])

Assert that x shallowly equals y with coercive equality using the == operator.

t.notEqual(x, y, [message])

Assert that x does not shallowly equal y with coercive equality using the != operator.

t.deepEqual(x, y, [message])

Assert that x deeply equals y using a recursive traversal of both arguments.

t.notDeepEqual(x, y, [message])

Assert that x doesn't not deeply equal y using a recursive traversal of both arguments.

t.strictEqual(x, y, [message])

Assert that x strictly equals y using the === operator.

t.notStrictEqual(x, y, [message])

Assert that x does not strictly equal y using the !== operator.

t.throws(cb, [error], [message])

Assert that the callback cb() will raise an exception when run. If error is specified, the exception should match error. error can be a constructor, regexp, or validation function.

t.doesNotThrow(cb, [error], [message])

Assert that the callback cb() will not raise an exception when run.


The test harness is made available via require() but you can also load other files. Require is provided by browserify, which emulates the require() in node.

relative requires

If your test upload spans multiple files, you'll be able to require() those other files with a relative path starting in a "./". Here's an example of a multi-file upload with relative requires:

package requires

Since testling uses browserify to bundle test uploads, you can install modules from npm into the node_modules/ directory. Modules in node_modules/ can then be loaded by just doing require('modulename').
See the using npm section for an example.


If you have code that isn't written using node-style module.exports, you can use require.load() instead.
For instance, if you have a file foo.js that defines a function foo():
function foo (x) {
    return x + 1;
then in your test.js test file you can do:
var test = require('testling');

test('foo', function (t) {
    t.deepEqual(foo(5), 6);
and after the require.load('./foo.js'), the function foo() will be defined in the global scope.
To run this example, just do:
robot : ~ $ tar -cf- foo.js test.js |
  curl -sSNT- localhost:8080/?browsers=chrome/14.0
Bundling...  done

chrome/14.0         1/1  100 % ok

total               1/1  100 % ok
robot : ~ $
See also the section on running multiple test files.

running tests

To run a test with testling, just send an HTTP PUT! The file that you PUT to testling.com can either be a single javascript file or a tar file with as many javascript files as you like.


Testling just uses basic auth over HTTP. Just use your browserling account email and password. Don't have an account? Create one!
Once you have an account, with curl you can just do:
curl -u me@example.com:mypassword -sSNT test.js testling.com
Or if you want to be prompted for your password you can do:
curl -u me@example.com -sSNT test.js testling.com

running a single test file

Running a single test file is super simple! Just send an HTTP PUT request to browserling with the contents of your test. Here's what that looks like using curl:
robot : ~ $ curl -sSNT test.js \
Bundling....  done

iexplore/6.0        1/1  100 % ok
iexplore/7.0        1/1  100 % ok
safari/5.0          1/1  100 % ok

total               3/3  100 % ok
robot : ~ $

running multiple test files

You can upload a tar file containing multiple files to run. The tar file must either contain a test.js or the main parameter must be specified so testling knows where to start executing.
Any other files should be executed from the main file using require() or require.load(). Your tar file may also contain HTML files that you can load with t.createWindow().
Suppose we've got a test.js:
var test = require('testling');
var b = require('./b');

test('multifile', function (t) {
    t.equal(b({ a : 3, b : 4 }), 2);
and the other file it uses, b.js, looks like:
module.exports = function (n) {
    return Object.keys(n).length
You can just make tar use stdout for output so that curl can read from a pipe and forward along both tests to testling:
robot : ~ $ tar -cf- test.js b.js | curl -sSNT- \
Bundling....  done

iexplore/9.0        1/1  100 % ok
chrome/13.0         1/1  100 % ok

total               2/2  100 % ok
robot : ~ $

stack traces

When an error occurs in a test, you'll get a full stack trace no matter which browser is being used. We make this work by rewriting the AST at runtime using burrito and stackedy.

query parameters

When you run a test, you can specify parameters in the query string of the HTTP PUT request.
For example with curl you can do:
curl -sSNT test.js \
to run your test.js in internet explorer 7 and firefox 3.5 with json output.

browsers parameter

This query parameter controls which browsers your test will run under. Use a comma separator to specify multiple browsers.
Click here to see which browsers we're running or use curl:

curl -s testling.com/browsers.json

output parameter

Specify the format for test output. The default output is text.


Display output with human-readable lines of text as they become available. Differences in deepEqual comparisons are rendered using difflet.


Display output as streaming json. That is, when the output is complete, the result will be valid json, but the elements in the json will be populated in realtime as the results come back from the browsers.
Specifically, testling uses JSONStream to write streaming json output. You can use JSONStream's .parse() to read the output as new elements arrive.


Display output with the Test Anything Protocol using node-tap. Like node-tap, differences in deepEqual comparisons are rendered using difflet!


Sometimes it's useful to just collect information from all the browsers. In output=log mode, a streaming json object is rendered populating each browser with json data from all the log messages. All error and assertion data is hidden.
Example output:


For cases when you just want to inject some <script> tags into the page before everything else, you can use the script query parameter. You can specify script=... as many times as you like and each script will be included into the page.
curl -sSNT test.js \


Sometimes instrumentation can cause problems. If you upload some big files and testling just hangs, the instrumenter could be hung up. You can disable the instrumentation with this field as a comma-separated list of files.
Or, you can disable instrumentation for all files by specifying ?noinstrument by itself without any files.
Here's an example:
tar -cf- beep.js boop.js | curl -sSNT- \


Sometimes you might want to pass in variables to your tests so that you don't have to modify your test.js with constants. Just use the argv parameter!
In your tests you can access process.argv just like in node:
var test = require('testling');

test('argv test', function (t) {
Now to run your test, just pass in argv on the query string.
robot : ~ $ curl -sSNT argv.js \
Bundling...  done

firefox/3.6         0/0    0 % ok
  Log: ["testling","/test.js","HELLO","WORLD!"]

total               0/0    0 % ok
robot : ~ $
Each argv will be another element in process.argv. The first two elements in process.argv are populated for compatability with node since you can also run testling tests locally.


If you want to specify a different entry point than "test.js" for multi-file uploads, use the main parameter on the query string.

running tests locally

You can run your testling tests locally too! With node.js and npm installed, just do:
npm install -g testling
Now to run a test, just use the testling command:
robot : ~ $ testling test.js
node/jsdom                      1/1  100 % ok
robot : ~ $ 
To run your test on real browsers, just add --browsers=... to the command:
robot : ~ $ testling test.js \
Bundling...  done

iexplore/7.0        0/1    0 % ok
  Error: 'JSON' is undefined
    at [anonymous]() in /test.js : line: 4, column: 5
    at [anonymous]() in /test.js : line: 3, column: 29
    at test() in /test.js : line: 3, column: 1

  > t.deepEqual(JSON.parse('[1,2]'), [1,2]);

iexplore/8.0        1/1  100 % ok
firefox/3.5         1/1  100 % ok

total               2/3   66 % ok
robot : ~ $ 
That was easy! The testling command will take care of remembering your account information for running tests on real testling.com browsers.
Check out the code on github!

using npm

Since testling uses browserify, you can use many node.js modules published to npm.
Suppose we'd like to use the traverse module in a new testling test. We can make a new test directory and install traverse into the node_modules directory with npm:
robot : ~ $ mkdir traverse-test
robot : ~ $ cd traverse-test/
robot : traverse-test $ npm install traverse
traverse@0.5.1 ./node_modules/traverse 
robot : traverse-test $ 
You might need to mkdir node_modules first to get the module to install into ./ if there is a node_modules in some parent directory.
Then in your test you can require('traverse'):
var test = require('testling');
var traverse = require('traverse');

test('scrub circular refs', function (t) {
    var obj =  { a : 1, b : 2, c : [ 3, 4 ] };
    var scrubbed = traverse(obj).map(function (x) {
        if (this.circular) this.remove()
    t.deepEqual(scrubbed, { a : 1, b : 2, c : [ 3, 4 ] });
To run your test, just upload a tar file of the whole directory:
robot : traverse-test $ tar -cf- . | curl -sSNT- \
Bundling....  done

iexplore/9.0        1/1  100 % ok

total               1/1  100 % ok
robot : traverse-test $ 

checking your account usage

To see how many minutes you've used, just visit testling.com with curl:
robot : traverse-test $ curl -u me@example.com -s \
Enter host password for user 'me@example.com':
You have used 51 out of 200 minutes this month.
robot : traverse-test $ 
Or if you prefer JSON output:
robot : traverse-test $ curl -u me@example.com -s \
Enter host password for user 'me@example.com':
robot : traverse-test $ 


You can use ssh tunnels to write testling tests that point at a web server that you're running locally.

uploading your public key

First you'll need to upload your ssh public key. Those usually live in ~/.ssh and will probably be either ~/.ssh/id_rsa.pub or ~/.ssh/id_dsa.pub.
If you have id_rsa.pub:
curl -u me@example.com -sST ~/.ssh/id_rsa.pub \
or if you have id_dsa.pub:
curl -u me@example.com -sST ~/.ssh/id_dsa.pub \

open a tunnel

To open a new ssh tunnel just do:
curl -u me@example.com testling.com/tunnel/open
The command will output the ssh command you can use to proxy your local service into testling.

close a tunnel

To close your open ssh tunnel you can run:
curl -u me@example.com testling.com/tunnel/close

tunnel status

To get information about tunnels you can do:
curl -u me@example.com testling.com/tunnel
This command will display the ssh commands you can execute to start a tunnel.
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.