Upcoming Official Symfony Conferences

Testing

2.1 version
Maintained Unmaintained

Testing

The Testing component is an internal tool for testing Symfony CMF bundles. It provides a way to easily bootstrap a consistent functional test environment.

Configuration

Composer

Add the following dependency to the require-dev section of composer.json:

1
2
3
"require-dev": {
    "symfony-cmf/testing": "1.2.*"
},

Note

The Testing component does not automatically include the SonataAdminBundle. You will need to manually add this dependency if required.

PHPUnit

The following file should be placed in the root directory of your bundle and named phpunit.xml.dist:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
    colors="true"
    bootstrap="vendor/symfony-cmf/testing/bootstrap/bootstrap.php"
>

    <testsuites>
        <testsuite name="Symfony <your bundle>Bundle Test Suite">
            <directory>./Tests</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist addUncoveredFilesFromWhitelist="true">
            <directory>.</directory>
            <exclude>
                <directory>Resources/</directory>
                <directory>Tests/</directory>
                <directory>vendor/</directory>
            </exclude>
        </whitelist>
    </filter>

    <php>
        <server name="KERNEL_DIR" value="Tests/Resources/app" />
    </php>

</phpunit>

AppKernel

The AppKernel should be placed in the ./Tests/Resources/app folder.

Below is the minimal AppKernel.php:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

use Symfony\Cmf\Component\Testing\HttpKernel\TestKernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends TestKernel
{
    public function configure()
    {
        $this->requireBundleSets(array(
            'default',
        ));

        $this->addBundles(array(
            new \Symfony\Cmf\Bundle\MyBundle\CmfMyBundle(),
        ));
    }

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load(__DIR__.'/config/config.php');
    }
}

Use $this->requireBundleSets('bundle_set_name') to include pre-configured sets of bundles:

  • default: Symfony's FrameworkBundle, TwigBundle and MonologBundle;
  • phpcr_odm: Doctrines DoctrineBundle and DoctrinePHPCRBundle;
  • sonata_admin: Sonata AdminBundle, BlockBundle and SonataDoctrinePHPCRAdminBundle.

For any other bundle requirements simply use $this->addBundles(array()) as in the example above.

Git

Place the following .gitignore file in your root directory:

1
2
3
4
Tests/Resources/app/cache
Tests/Resources/app/logs
composer.lock
vendor

Travis

The following file should be named .travis.yml (note the leading ".") and placed in the root directory of your bundle:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
language: php

php:
  - 5.3
  - 5.4
  - 5.5

env:
  - SYMFONY_VERSION=2.2.*
  - SYMFONY_VERSION=2.3.*
  - SYMFONY_VERSION=dev-master

before_script:
  - composer require symfony/symfony:${SYMFONY_VERSION}
  - vendor/symfony-cmf/testing/bin/travis/phpcr_odm_doctrine_dbal.sh

script: phpunit --coverage-text

notifications:
  irc: "irc.freenode.org#symfony-cmf"
  email: "symfony-cmf-devs@googlegroups.com"

matrix:
  allow_failures:
    - env: SYMFONY_VERSION=dev-master

Implementing the Component

You should try and build a working application for testing your bundle. The application can be accessed using the server command detailed in this document.

Test Types

  • Unit - The scope of a unit test should be limited testing a single class instance. All other dependencies should be mocked;
  • Functional - Functional tests will test a single service as retrieved from the dependency injection container;
  • Web - Web test cases are the most holistic tests. They use the browser kit to make web requests on the kernel, testing the whole stack.

Test File Organization

Test files and tests should be organized as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
./Tests/
    ./Unit
        ./Full/Namespace/<test>Test.php
        ./Document/BlogTest.php
        ./Document/PostTest.php
        [...]
    ./Functional
        ./MyService/SomeServiceTest.php
        [...]
    ./WebTest
        ./Admin/SomeAdminTest.php
        ./Controller/MyControllerTest.php
    ./Resources
        ./app
            ./AppKernel.php
            ./config/
                ./config.php
        ./DataFixtures/
            ./Phpcr/
                 ./LoadFoobarFixtures.php
        ./Document/
            Foobar.php

Custom Documents

The Testing component will automatically include PHPCR-ODM documents that are placed in Tests/Resources/Document.

Configuration

The Testing component includes some pre-defined configurations to get things going with a minimum of effort and repetition.

To implement the default configurations create the following PHP file:

// Tests/Resources/app/config/config.php
$loader->import(CMF_TEST_CONFIG_DIR.'/default.php');
$loader->import(__DIR__.'/mybundleconfig.yml');

Here you include the Testing component's default configuration, which will get everything up-and-running. You can then optionally import configurations specific to your bundle.

The available default configurations are as follows, and correspond to the bundle sets above:

  • default.php: framework, doctrine, security;
  • sonata_admin.php: sonata_admin, sonata_block;
  • phpcr-odm.php: doctrine_phpcr.

Note that each must be prefixed with the CMF_TEST_CONFIG_DIR constant.

Routing Configuration

You must include a routing.php file in the same directory as the configuration above:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php

use Symfony\Component\Routing\RouteCollection;

$collection = new RouteCollection();
$collection->addCollection(
    $loader->import(CMF_TEST_CONFIG_DIR.'/routing/sonata_routing.yml')
);
$collection->addCollection(
    $loader->import(__DIR__.'/routing/my_test_routing.yml')
);

return $collection;

The following default routing configurations are available:

  • sonata_routing.yml: sonata admin and dashboard.

The above files must be prefixed with CMF_TEST_CONFIG_DIR.'/routing/' as in the example above.

The Console

The console for your test application can be accessed as follows:

1
$ php vendor/symfony-cmf/testing/bin/console

Test Web Server

The Testing component provides a wrapper for the Symfony server:run command.

1
$ php vendor/symfony-cmf/testing/bin/server

Which basically does the following:

1
2
3
$ php vendor/symfony-cmf/testing/bin/console server:run \
    --router=vendor/symfony-cmf/testing/resources/web/router.php \
    --docroot=vendor/symfony-cmf/testing/resources/web

You can then access your test application in your browser at http://localhost:8000.

Note

The server and the requests default to using the phpcr configuration environment. Its possible to use a different environment by using --env/-e as arguments for the CLI command and a GET parameter env for web requests.

Publish assets in the directory named above using the testing console as follows:

1
2
$ php vendor/symfony-cmf/testing/bin/console assets:install \
    vendor/symfony-cmf/testing/resources/web

Initializing the Test Environment

Before running your (functional) tests you will need to initialize the test environment (i.e. the database). You could do this manually, but it is easier to do this the same way that travis will do it, as follows:

1
$ ./vendor/symfony-cmf/testing/bin/travis/phpcr_odm_doctrine_dbal.sh

Functional and Web Testing

In general your functional tests should extend Symfony\Cmf\Component\Testing\Functional\BaseTestCase. This class will provide you with some helpers to make testing easier.

PHPCR-ODM

Accessing the Document Manager

Access as:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$manager = $this->db('PHPCR');
$documentManager = $this->db('PHPCR')->getOm();

// create a test node /test
$this->db('PHPCR')->createTestNode();

// load fixtures
$this->db('PHPCR')->loadFixtures(array(
    // ... fixture classes here
));

Support Files

The Testing component includes some basic documents which will automatically be mapped by PHPCR-ODM:

  • Symfony\Cmf\Testing\Document\Content: Minimal referenceable content document.

ORM

The Testing component also provides support for testing the ORM.

Accessing the Entity Manager

You can access the Entity Manager and repository using:

$entityManager = $this->db('ORM')->getOm();

Separating PHPCR and ORM configuration

Most of the time, you cannot load both the PHPCR and ORM configuration. The Testing component uses environments to separate these configurations. First, create a file config_phpcr.php which loads all needed configuration for the PHPCR and a file config_orm.php which loads all needed configuration for the ORM. After that, edit the AppKernel::registerContainerConfiguration to be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
use Symfony\Cmf\Component\Testing\HttpKernel\TestKernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends TestKernel
{
    // ...

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load(__DIR__.'/config/config_'.$this->environment.'.php');
    }
}

After that, all ORM tests should override the getKernelConfiguration method of the BaseTestCase to set the environment to orm:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// ...
use Symfony\Cmf\Component\Testing\Functional\BaseTestCase;

class MyOrmTest extends BaseTestCase
{
    protected function getKernelConfiguration()
    {
        return array(
            'environment' => 'orm',
        );
    }
}

Tip

It's recommend to put this in a OrmTestCase class which lives inside your bundle and let all Orm tests extends this class.

Note

This isn't needed for PHPCR, as the environment automatically defaults to phpcr.

Running Commands using the ORM Configuration

Add --env=orm to the commands which need to ORM configuration as well as &env=orm to web requests requiring the ORM configuration.

Editing Travis Configuration

If a bundle adds functional tests for ORM, the travis configuration needs to be changed in order to correctly setup the environment.

Change the before_script section to:

1
2
3
before_script:
  - composer require symfony/framework-bundle:${SYMFONY_VERSION}
  - vendor/symfony-cmf/testing/bin/travis/phpcr_odm_doctrine_orm_dbal.sh

Caution

This script executes the doctrine:schema:create command in the orm environment. This will set up both the PHPCR and ORM schemas. To make it work, you have to include the PHPCR configuration in the ORM configuration.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.