.. _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 `_.