< Code Convention

Code Documentation >

## 7. Unit Tests

## 7.1. Introduction

Unit tests are an important componant in the CartoWeb development environment. The framework used for unit testing is based on PHPUnit2, a PEAR package. For more informations abouth PHPUnit2, see http://pear.php.net/reference/PHPUnit2-2.0.3/

PHPUnit2 is included in the libraries shipped with CartoWeb. Thus, no installation is needed to run and write new tests.

## 7.2. Writing Tests

Information about writing tests for CartoWeb can be separated into two parts. First part about writing Unit tests in general, useful for people new to PhpUnit. Then a part more specific about the infrastructure which is available in CartoWeb for writing tests.

### 7.2.1. General Information About Writing Tests

Test cases are located in directory `tests` for testing the core of CartoWeb and in the directories `<project>/tests` for for tests specific to project `<project>`. Inside these `tests` directories, path hierarchy mirrors the existing hierarchy they are testing. For instance, the `tests` hierarchy for the core CartoWeb testing is the following:

    client
        CartoclientTest.php
        CartoserverServiceTest.php
        AllTests.php
    common
        BasicTypesTest.php
        AllTests.php
    coreplugins
        AllTests.php
        ...
    plugins
        AllTests.php
        ...

For the `test_main` project, the hierarchy is the following:

    coreplugins
        AllTests.php
        ...
    plugins
        AllTests.php
        ...
    misc
        AllTests.php
        < misc tests >
        ...
    ...

Each directory including tests root directory has a file named `AllTests.php`. This is called a test suite. It is used to run all tests of a specific directory (ie "package").

### Warning

All test case and test suite classes must have the name of their file relative path without extension, with '/' replaced by '_'. For instance, class `client_CartoclientTest` file name must be `<cartoweb3_root>/tests/client/CartoclientTest.php`.

The following example shows a test in `common/BasicTypeTest.php` file:

Example 7.1. Simple test case (`BasicTypesTests.php`)

    <?php
    require_once 'PHPUnit2/Framework/TestCase.php';
    require_once(CARTOWEB_HOME . 'common/basic_types.php');

    class common_BasicTypesTest extends PHPUnit2_Framework_TestCase {

            public function testBboxFrom2Points() {

                    $bbox = new Bbox();
                    $point1 = new Point(12, 34);
                    $point2 = new Point(56, 78);
                    $bbox->SetFrom2Points($point1, $point2);

                    $this->assertEquals(12, $bbox->minx);
                    $this->assertEquals(34, $bbox->miny);
                    $this->assertEquals(56, $bbox->maxx);
                    $this->assertEquals(78, $bbox->maxy);
            }
    }
    ?>

Each function with name starting with 'test' will be considered as a test case by the automated test runner. You may also want to use functions `setUp()` and `tearDown()` to initialize and clean a test environment.

Method `assertEquals` tests if two values have the same values. If not, the test will be added to the final report as failure.

As stated previously, all test classes have to belong to a test suite. The next example shows how such a test suite is built, by grouping all tests together in the `suite()` method.

Example 7.2. Test suite (`AllTests.php`)

    <?php

    require_once 'PHPUnit2/Framework/TestSuite.php';
    require_once 'CartoclientTest.php';
    require_once 'CartoserverServiceTest.php';

    class client_AllTests {

            public static function suite() {

                    $suite = new PHPUnit2_Framework_TestSuite;

                    $suite->addTestSuite('client_CartoclientTest');
                    $suite->addTestSuite('client_CartoserverServiceTest');

                    return $suite;
            }
    }
    ?>

All test suites are then grouped together into the root test suite. It is shown there for information.

Example 7.3. Root directory's AllTests.php:

    <?php

    require_once 'PHPUnit2/Framework/TestSuite.php';
    require_once 'client/AllTests.php';
    require_once 'common/AllTests.php';

    class AllTests {

            public static function suite() {

                    $suite = new PHPUnit2_Framework_TestSuite;

                    $suite->addTest(client_AllTests::suite());
                    $suite->addTest(common_AllTests::suite());

                    return $suite;
            }
    }
    ?>

### 7.2.2. Specific Information for Tests

This section describes specific features developped in CartoWeb for running tests, and infrastructure classes for more simple test case writing.

#### 7.2.2.1. HttpUnit Based Tests

To test features of the cartoclient, the HttpUnit software is used. It is written in Java, and there is no Php port. The http unit tests are run if you have a JVM in you path.

For more information about running HttpUnit tests, see the `tests/client/httpunit/README` file in the CartoWeb distribution.

#### 7.2.2.2. Testing CartoWeb Plugins

Plugins are a main component in CartoWeb architecture. That's why there is support to maintain common code used for testing plugins. As described in Section 7.2.1, “General Information About Writing Tests” the tests for plugins have to mirror the file hierarchy of the base application. That's why there are `coreplugins` and `plugins` directories where test for core plugins and plugins are stored respectively.

### Note

Tests are also available for projects. So, to test a plugin in a project, the path of the test will be `<cartoweb3>/<projectname>/tests/plugin/<pluginname>`

Testing plugins is separated into two tasks:

1. Locally testing client, common or server classes. For plugin client classes, it requires a CartoClient environment available, and identically a CartoServer environment for testing server classes.
2. Remote plugin tests, throught the webservice API. This kind of tests are related to the server plugins, that's why we chose to put them in the `server` folder of plugins.

For the first point mentionned above, general Unit tests rules apply, as described in Section 7.2.1, “General Information About Writing Tests”.

For the second point stated, a help class named `client_CartoserverServiceTest` can be extended by the testing classes. In turn, `client_CartoserverServiceTest` extends other classes which offer additional helpful methods. For the complete list of available methods, please have a look at the generate API docs (as more may be added in future). The main useful methods are `createRequest()` for initializing a new request, `getMap()` for lanching the request.

### Tip

Having a look at an existing plugin test case is the best starting point for writing new tests.

#### 7.2.2.3. Tests for projects

Each CartoWeb project can have its set of tests directly inside the project, in a directory `tests`. Inside this directory, you have to use the same hierarchy as in the main `tests` directory.

Inside these `tests` directories, the same mechanism is used for testing as the main `tests` directory. The best way to get started is to have a look at the `test_main` project for a starting point.

##### 7.2.2.3.1. Invoking tests for a specific project

For now, only the command line can be used for invoking tests for a specific project. An environment variable CARTOWEB_TEST_PROJECT can be used to define which test to launch. Under a Unix like shell enviroment, the command line to use is:

    CARTOWEB_TEST_PROJECT=<myproject> <php-bin> phpunit.php projects_AllTests projects/AllTests.php

## 7.3. Running Tests

Unit tests are runned using the command line interface (CLI). To run a test case or a test suite, type the following command in directory `<cartoweb3_root>/tests`:

    <php-bin> phpunit.php <test-class> <php-file>

Where <php-bin> is the PHP binary, <test-class> is the name of the test class (`AllTests`, `client_AllTests`, `client_CartoclientTest`, etc.) and <php-file> is the name of the PHP file containing the test case (`client/CartoclientTest.php`).

Result should look like this:

    PHPUnit 2.0.3 by Sebastian Bergmann.

    .......F.....

    Time: 0.0410950183868
    There was 1 failure:
    1) testpointtobbox
    expected same: <113> was not: <123>
    /home/yves/cartoweb3-proto2/tests/common/BasicTypesTest.php:59
    /home/yves/cartoweb3-proto2/tests/phpunit.php:24

    FAILURES!!!
    Tests run: 12, Failures: 1, Errors: 0, Incomplete Tests: 0.
    Content-type: text/html
    X-Powered-By: PHP/5.0.1

In this case, 12 tests were run with one failure.