/doc/testing.rst
ReStructuredText | 222 lines | 166 code | 56 blank | 0 comment | 0 complexity | a4a1a3cc8c1d721f1da03ba378cca3a0 MD5 | raw file
- Testing
- =======
- Because Silex is built on top of Symfony, it is very easy to write functional
- tests for your application. Functional tests are automated software tests that
- ensure that your code is working correctly. They go through the user interface,
- using a fake browser, and mimic the actions a user would do.
- Why
- ---
- If you are not familiar with software tests, you may be wondering why you would
- need this. Every time you make a change to your application, you have to test
- it. This means going through all the pages and making sure they are still
- working. Functional tests save you a lot of time, because they enable you to
- test your application in usually under a second by running a single command.
- For more information on functional testing, unit testing, and automated
- software tests in general, check out `PHPUnit
- <https://github.com/sebastianbergmann/phpunit>`_ and `Bulat Shakirzyanov's talk
- on Clean Code <http://www.slideshare.net/avalanche123/clean-code-5609451>`_.
- PHPUnit
- -------
- `PHPUnit <https://github.com/sebastianbergmann/phpunit>`_ is the de-facto
- standard testing framework for PHP. It was built for writing unit tests, but it
- can be used for functional tests too. You write tests by creating a new class,
- that extends the ``PHPUnit_Framework_TestCase``. Your test cases are methods
- prefixed with ``test``::
- class ContactFormTest extends \PHPUnit_Framework_TestCase
- {
- public function testInitialPage()
- {
- ...
- }
- }
- In your test cases, you do assertions on the state of what you are testing. In
- this case we are testing a contact form, so we would want to assert that the
- page loaded correctly and contains our form::
- public function testInitialPage()
- {
- $statusCode = ...
- $pageContent = ...
- $this->assertEquals(200, $statusCode);
- $this->assertContains('Contact us', $pageContent);
- $this->assertContains('<form', $pageContent);
- }
- Here you see some of the available assertions. There is a full list available
- in the `Writing Tests for PHPUnit
- <https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html>`_
- section of the PHPUnit documentation.
- WebTestCase
- -----------
- Symfony provides a WebTestCase class that can be used to write functional
- tests. The Silex version of this class is ``Silex\WebTestCase``, and you can
- use it by making your test extend it::
- use Silex\WebTestCase;
- class ContactFormTest extends WebTestCase
- {
- ...
- }
- .. caution::
- If you need to override the ``setUp()`` method, don't forget to call the
- parent (``parent::setUp()``) to call the Silex default setup.
- .. note::
- If you want to use the Symfony ``WebTestCase`` class you will need to
- explicitly install its dependencies for your project:
- .. code-block:: bash
- composer require --dev symfony/browser-kit symfony/css-selector
- For your WebTestCase, you will have to implement a ``createApplication``
- method, which returns your application instance::
- public function createApplication()
- {
- // app.php must return an Application instance
- return require __DIR__.'/path/to/app.php';
- }
- Make sure you do **not** use ``require_once`` here, as this method will be
- executed before every test.
- .. tip::
- By default, the application behaves in the same way as when using it from a
- browser. But when an error occurs, it is sometimes easier to get raw
- exceptions instead of HTML pages. It is rather simple if you tweak the
- application configuration in the ``createApplication()`` method like
- follows::
- public function createApplication()
- {
- $app = require __DIR__.'/path/to/app.php';
- $app['debug'] = true;
- unset($app['exception_handler']);
- return $app;
- }
- .. tip::
- If your application use sessions, set ``session.test`` to ``true`` to
- simulate sessions::
- public function createApplication()
- {
- // ...
- $app['session.test'] = true;
- // ...
- }
- The WebTestCase provides a ``createClient`` method. A client acts as a browser,
- and allows you to interact with your application. Here's how it works::
- public function testInitialPage()
- {
- $client = $this->createClient();
- $crawler = $client->request('GET', '/');
- $this->assertTrue($client->getResponse()->isOk());
- $this->assertCount(1, $crawler->filter('h1:contains("Contact us")'));
- $this->assertCount(1, $crawler->filter('form'));
- ...
- }
- There are several things going on here. You have both a ``Client`` and a
- ``Crawler``.
- You can also access the application through ``$this->app``.
- Client
- ~~~~~~
- The client represents a browser. It holds your browsing history, cookies and
- more. The ``request`` method allows you to make a request to a page on your
- application.
- .. note::
- You can find some documentation for it in `the client section of the
- testing chapter of the Symfony documentation
- <http://symfony.com/doc/current/book/testing.html#the-test-client>`_.
- Crawler
- ~~~~~~~
- The crawler allows you to inspect the content of a page. You can filter it
- using CSS expressions and lots more.
- .. note::
- You can find some documentation for it in `the crawler section of the testing
- chapter of the Symfony documentation
- <http://symfony.com/doc/current/book/testing.html#the-test-client>`_.
- Configuration
- -------------
- The suggested way to configure PHPUnit is to create a ``phpunit.xml.dist``
- file, a ``tests`` folder and your tests in
- ``tests/YourApp/Tests/YourTest.php``. The ``phpunit.xml.dist`` file should
- look like this:
- .. code-block:: xml
- <?xml version="1.0" encoding="UTF-8"?>
- <phpunit bootstrap="./vendor/autoload.php"
- backupGlobals="false"
- backupStaticAttributes="false"
- colors="true"
- convertErrorsToExceptions="true"
- convertNoticesToExceptions="true"
- convertWarningsToExceptions="true"
- processIsolation="false"
- stopOnFailure="false"
- syntaxCheck="false"
- >
- <testsuites>
- <testsuite name="YourApp Test Suite">
- <directory>./tests/</directory>
- </testsuite>
- </testsuites>
- </phpunit>
- Your ``tests/YourApp/Tests/YourTest.php`` should look like this::
- namespace YourApp\Tests;
- use Silex\WebTestCase;
- class YourTest extends WebTestCase
- {
- public function createApplication()
- {
- return require __DIR__.'/../../../app.php';
- }
- public function testFooBar()
- {
- ...
- }
- }
- Now, when running ``phpunit`` on the command line, tests should run.