testing.rst 10.2 KB

.. _testing:

.. index:: Testing

=======
Testing
=======

CasperJS ships with its own :doc:`testing framework `, providing a handful set of tools to ease testing your webapps.

.. warning::

.. versionchanged:: 1.1

The testing framework — hence its whole API — can only be used when using the ``casperjs test`` subcommand:

- If you try to use the ``casper.test`` property out of the testing environment, you'll get an error;
- As of 1.1-beta3, you can't override the preconfigured ``casper`` instance in this test environment. You can read more about the whys in the :ref:`dedicated FAQ entry `.

.. index:: Unit testing

Unit testing
------------

Imagine a dumb ``Cow`` object we want to unit test::

function Cow() {
this.mowed = false;
this.moo = function moo() {
this.mowed = true; // mootable state: don't do that at home
return 'moo!';
};
}

Let's write a tiny test suite for it::

// cow-test.js
casper.test.begin('Cow can moo', 2, function suite(test) {
var cow = new Cow();
test.assertEquals(cow.moo(), 'moo!');
test.assert(cow.mowed);
test.done();
});

Run the tests using the ``casperjs test`` command:

.. code-block:: text

$ casperjs test cow-test.js

You should theoretically get something like this:

.. figure:: _static/images/cow-test-ok.png
:align: center

Make it fail::

casper.test.begin('Cow can moo', 2, function suite(test) {
var cow = new Cow();
test.assertEquals(cow.moo(), 'BAZINGA!');
test.assert(cow.mowed);
test.done();
});

You'll get this instead:

.. figure:: _static/images/cow-test-ko.png
:align: center

.. hint::

The whole ``tester`` module API is documented :doc:`here `.

.. index:: Functional testing, Browser testing, Test suite

Browser tests
-------------

Now let's write a suite for testing google search (yes, you read it well)::

// googletesting.js
casper.test.begin('Google search retrieves 10 or more results', 5, function suite(test) {
casper.start("http://www.google.fr/", function() {
test.assertTitle("Google", "google homepage title is the one expected");
test.assertExists('form[action="/search"]', "main form is found");
this.fill('form[action="/search"]', {
q: "casperjs"
}, true);
});

casper.then(function() {
test.assertTitle("casperjs - Recherche Google", "google title is ok");
test.assertUrlMatch(/q=casperjs/, "search term has been submitted");
test.assertEval(function() {
return __utils__.findAll("h3.r").length >= 10;
}, "google search for \"casperjs\" retrieves 10 or more results");
});

casper.run(function() {
test.done();
});
});

Now run the tests suite:

.. code-block:: text

$ casperjs test googletesting.js

You'll probably get something like this:

.. figure:: _static/images/testsuiteok.png
:align: center

.. index:: options

Setting Casper options in the test environment
----------------------------------------------

As you must use a preconfigured ``casper`` instance within the test environment, updating its :ref:`options ` can be achieved this way::

casper.options.optionName = optionValue; // where optionName is obviously the desired option name

casper.options.clientScripts.push("new-script.js");

.. index:: setUp, tearDown

Advanced techniques
-------------------

The :ref:`Tester#begin() ` accepts either a function or an object to describe a suite; the object option allows to set up ``setUp()`` and ``tearDown()`` functions::

// cow-test.js
casper.test.begin('Cow can moo', 2, {
setUp: function(test) {
this.cow = new Cow();
},

tearDown: function(test) {
this.cow.destroy();
},

test: function(test) {
test.assertEquals(this.cow.moo(), 'moo!');
test.assert(this.cow.mowed);
test.done();
}
});

.. _test_subcomand:

Test command args and options
-----------------------------

Arguments
~~~~~~~~~

The ``casperjs test`` command will treat every passed argument as file or directory paths containing tests. It will recursively scan any passed directory to search for ``*.js`` or ``*.coffee`` files and add them to the stack.

.. warning ::

There are two important conditions when writing tests:

- You **must not** create a new ``Casper`` instance in a test file;
- You **must** call ``Tester.done()`` when all the tests contained in a suite (or in a file) have been executed.

Options
~~~~~~~

Options are prefixed with a double-dash (``--``):

- ``--xunit=`` will export test suite results in a :ref:`XUnit XML file `
- ``--direct`` or ``--verbose`` will print :doc:`log messages ` directly to the console
- ``--log-level=`` sets the logging level (see the :doc:`related section `)
- ``--auto-exit=no`` prevents the test runner to exit when all the tests have been executed; this usually allows performing supplementary operations, though implies to exit casper manually listening to the ``exit`` tester event::

// $ casperjs test --auto-exit=no
casper.test.on("exit", function() {
someTediousAsyncProcess(function() {
casper.exit();
});
});

.. versionadded:: 1.0

- ``--includes=foo.js,bar.js`` will include the ``foo.js`` and ``bar.js`` files before each test file execution.
- ``--pre=pre-test.js`` will add the tests contained in ``pre-test.js`` **before** executing the whole test suite.
- ``--post=post-test.js`` will add the tests contained in ``post-test.js`` **after** having executed the whole test suite.
- ``--fail-fast`` will terminate the current test suite as soon as a first failure is encountered.
- ``--concise`` will create a more concise output of the test suite.
- ``--no-colors`` will create an output without (beautiful) colors from casperjs.

Sample custom command:

.. code-block:: text

$ casperjs test --includes=foo.js,bar.js \
--pre=pre-test.js \
--post=post-test.js \
--direct \
--log-level=debug \
--fail-fast \
test1.js test2.js /path/to/some/test/dir

.. warning::

.. deprecated:: 1.1

``--direct`` option has been renamed to ``--verbose``, though ``--direct`` will still works, while is to be considered deprecated.

.. hint::

A `demo gist `_ is also available in order to get you started with a sample suite involving some of these options.

.. _xunit_report:

.. index:: XUnit, XML, Jenkins, Continuous Integration

Exporting results in XUnit format
---------------------------------

CasperJS can export the results of the test suite to an XUnit XML file, which is compatible with continuous integration tools such as `Jenkins `_. To save the XUnit log of your test suite, use the ``--xunit`` option:

.. code-block:: text

$ casperjs test googletesting.js --xunit=log.xml

You should get a pretty XUnit XML report like this:

.. code-block:: xml











You can customize the value for the `name` property by passing an object to `casper.test.fail()` like:

.. code-block:: js

casper.test.fail('google search for "casperjs" retrieves 10 or more results', {name: 'result count is 10+'});

.. code-block:: xml









google search for "casperjs" retrieves 10 or more results


CasperJS own tests
------------------

CasperJS has its own unit and functional test suite, located in the ``tests`` subfolder. To run this test suite:

.. code-block:: text

$ casperjs selftest

.. note::

Running this test suite is a great way to find any bug on your platform. If it fails, feel free to `file an issue `_ or to ask on the `CasperJS mailing-list `_.

.. index:: extending

Extending Casper for Testing
----------------------------

This command:

.. code-block:: text

$ casperjs test [path]

is just a shortcut for this one:

.. code-block:: text

$ casperjs /path/to/casperjs/tests/run.js [path]

So if you want to extend Casper capabilities for your tests, your best bet is to write your own runner and extend the casper object instance from there.

.. hint::

You can find the default runner code in `run.js `_.