Skip to content

Commit 3428726

Browse files
authored
Merge pull request #14 from Nyholm/pr-14731
Started to work on the testing PR
2 parents 78c2531 + a17bd8a commit 3428726

File tree

1 file changed

+78
-113
lines changed

1 file changed

+78
-113
lines changed

testing.rst

+78-113
Original file line numberDiff line numberDiff line change
@@ -15,67 +15,57 @@ Symfony integrates with an independent library called `PHPUnit`_ to give you a
1515
rich testing framework. This article won't cover PHPUnit itself, which has its
1616
own excellent `documentation`_.
1717

18-
Before creating your first test, install the `PHPUnit Bridge component`_, which
19-
wraps the original PHPUnit binary to provide additional features:
18+
Before creating your first test, install the PHPUnit with the following command:
2019

2120
.. code-block:: terminal
2221
23-
$ composer require --dev symfony/phpunit-bridge
22+
$ composer require --dev phpunit/phpunit
2423
25-
After the library downloads, try executing PHPUnit by running (the first time
26-
you run this, it will download PHPUnit itself and make its classes available in
27-
your app):
24+
After the library is installed, try executing PHPUnit by running:
2825

2926
.. code-block:: terminal
3027
31-
$ ./bin/phpunit
28+
$ ./vendor/bin/phpunit
3229
3330
.. note::
3431

35-
The ``./bin/phpunit`` command is created by :ref:`Symfony Flex <symfony-flex>`
36-
when installing the ``phpunit-bridge`` package. If the command is missing, you
37-
can remove the package (``composer remove symfony/phpunit-bridge``) and install
38-
it again. Another solution is to remove the project's ``symfony.lock`` file and
39-
run ``composer install`` to force the execution of all Symfony Flex recipes.
32+
:ref:`Symfony Flex <symfony-flex>` has automatically created ``phpunit.xml.dist``
33+
and ``tests/bootstrap.php``. If the files are missing, you can remove the package
34+
(``composer remove phpunit/phpunit``) and install it again.
4035

4136
Each test is a PHP class that should live in the ``tests/`` directory of
4237
your application. If you follow this rule, then you can run all of your
4338
application's tests with the same command as before.
4439

45-
PHPUnit is configured by the ``phpunit.xml.dist`` file in the root of your
46-
Symfony application.
47-
48-
.. tip::
49-
50-
Use the ``--coverage-*`` command options to generate code coverage reports.
51-
Read the PHPUnit manual to learn more about `code coverage analysis`_.
40+
PHPUnit is configured by the ``phpunit.xml.dist`` file in the root of your application.
5241

5342
Types of Tests
5443
--------------
5544

45+
To get a common language and shared context, it is important to define a what different
46+
types of tests really mean. Symfony will use the following definition. If you have
47+
learned something different, that is not necessarily wrong. It is just different
48+
from what the Symfony documentation is using.
49+
5650
`Unit Tests`_
5751
These tests ensure that *individual* units of source code (e.g. a single
5852
class) behave as intended.
5953

6054
`Integration Tests`_
6155
These tests test a combination of classes and commonly interact with
6256
Symfony's service container. These tests do not yet cover the full
63-
working application, those are called *Functional tests*.
57+
working application, those are called *Application tests*.
6458

65-
`Functional Tests`_
66-
Functional tests test the behavior of a complete application. They
59+
`Application Tests`_
60+
Application tests test the behavior of a complete application. They
6761
make HTTP requests and test that the response is as expected.
6862

69-
`End to End Tests (E2E)`_
70-
At last, end to end tests test the application as a real user. They use
71-
a real browser and real integrations with external services.
72-
7363
Unit Tests
7464
----------
7565

7666
A `unit test`_ ensures that individual units of source code (e.g. a single
7767
class or some specific method in some class) meet their design and behave
78-
as intended. Writing Symfony unit tests is no different from writing
68+
as intended. Writing unit tests is a Symfony application no different from writing
7969
standard PHPUnit unit tests. You can learn about it in the PHPUnit
8070
documentation: `Writing Tests for PHPUnit`_.
8171

@@ -85,103 +75,66 @@ of your application for unit tests. So, if you're testing a class in the
8575
Autoloading is automatically enabled via the ``vendor/autoload.php`` file
8676
(as configured by default in the ``phpunit.xml.dist`` file).
8777

88-
You can run tests using the ``bin/phpunit`` command:
78+
You can run tests using the ``./vendor/bin/phpunit`` command:
8979

9080
.. code-block:: terminal
9181
9282
# run all tests of the application
93-
$ php bin/phpunit
83+
$ php ./vendor/bin/phpunit
9484
9585
# run all tests in the Util/ directory
96-
$ php bin/phpunit tests/Util
86+
$ php ./vendor/bin/phpunit tests/Util
9787
9888
# run tests for the Calculator class
99-
$ php bin/phpunit tests/Util/CalculatorTest.php
89+
$ php ./vendor/bin/phpunit tests/Util/CalculatorTest.php
10090
10191
Integration Tests
10292
-----------------
10393

104-
TODO: KernelTestCase
94+
An integration test will test a larger part of your application compared to a unit
95+
test. Integration tests will use the Kernel to fetch a service from the dependency
96+
injection container.
10597

106-
Accessing the Container
107-
~~~~~~~~~~~~~~~~~~~~~~~
108-
109-
You can get the same container used in the application, which only includes
110-
the public services::
111-
112-
public function testSomething()
113-
{
114-
$kernel = self::bootKernel();
115-
$container = $kernel->getContainer();
116-
$someService = $container->get('the-service-ID');
117-
118-
// ...
119-
}
120-
121-
Symfony tests also have access to a special container that includes both the
98+
Symfony tests have access to a special container that includes both the
12299
public services and the non-removed :ref:`private services <container-public>`
123100
services::
124101

125-
public function testSomething()
126-
{
127-
// this call is needed; otherwise the container will be empty
128-
self::bootKernel();
102+
// tests/Service/AcmeServiceTest.php
103+
namespace App\Tests\Service;
129104

130-
$container = self::$container;
131-
// $someService = $container->get('the-service-ID');
132-
133-
// ...
134-
}
135-
136-
.. TODO is this really different from self::$container and how to access
137-
this in KernelTestCase?
138-
139-
Finally, for the most rare edge-cases, Symfony includes a special container
140-
which provides access to all services, public and private. This special
141-
container is a service that can be get via the normal container::
105+
use App\Service\AcmeService;
106+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
142107

108+
class AcmeServiceTest extends KernelTestCase
109+
{
143110
public function testSomething()
144111
{
145-
$client = self::createClient();
146-
$normalContainer = $client->getContainer();
147-
$specialContainer = $normalContainer->get('test.service_container');
112+
// this call is needed; otherwise the container will be empty
113+
self::bootKernel();
148114

149-
// $somePrivateService = $specialContainer->get('the-service-ID');
115+
$container = self::$container;
116+
$someService = $container->get(AcmeService::class);
150117

151-
// ...
118+
$result = $someService->something();
119+
$this->assertTrue($result);
152120
}
121+
}
153122

154-
Mocking Services
155-
~~~~~~~~~~~~~~~~
156-
157-
TODO
158-
159-
.. _functional-tests:
160-
161-
Functional Tests
162-
----------------
163-
164-
Functional tests check the integration of the different layers of an
165-
application (from the routing to the views). They are no different from unit
166-
tests as far as PHPUnit is concerned, but they have a very specific workflow:
167-
168-
* Make a request;
169-
* Click on a link or submit a form;
170-
* Test the response;
171-
* Rinse and repeat.
172-
173-
Before creating your first test, install the ``symfony/test-pack`` which
174-
requires multiple packages providing some of the utilities used in the
175-
tests:
123+
.. tip::
176124

177-
.. code-block:: terminal
125+
To run your application tests, the ``KernelTestCase`` class needs to know which
126+
is the application kernel to bootstrap it. The kernel class is usually
127+
defined in the ``KERNEL_CLASS`` environment variable (included in the
128+
default ``.env.test`` file provided by Symfony Flex):
178129

179-
$ composer require --dev symfony/test-pack
130+
If your use case is more complex, you can also override the
131+
``createKernel()`` or ``getKernelClass()`` methods of your functional test,
132+
which take precedence over the ``KERNEL_CLASS`` env var.
180133

181134
Set-up your Test Environment
182135
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
183136

184-
The Client used by functional tests creates a Kernel that runs in a special
137+
The tests creates a Kernel that runs in a special
185138
``test`` environment. Since Symfony loads the ``config/packages/test/*.yaml``
186139
in the ``test`` environment, you can tweak any of your application's settings
187140
specifically for testing.
@@ -229,7 +182,7 @@ You can also use a different environment entirely, or override the default
229182
debug mode (``true``) by passing each as options to the ``createClient()``
230183
method::
231184

232-
$client = static::createClient([
185+
self::bootKernel([
233186
'environment' => 'my_test_env',
234187
'debug' => false,
235188
]);
@@ -293,7 +246,7 @@ that ensures that each test is run with the same unmodified database:
293246
294247
$ composer require --dev dama/doctrine-test-bundle
295248
296-
Now, enable it as a PHPUnit extension or listener:
249+
Now, enable it as a PHPUnit extension:
297250

298251
.. code-block:: xml
299252
@@ -366,10 +319,34 @@ Empty the database and reload *all* the fixture classes with:
366319
367320
For more information, read the `DoctrineFixturesBundle documentation`_.
368321

369-
Write Your First Functional Test
370-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
322+
.. _functional-tests:
323+
324+
Application Tests
325+
-----------------
326+
327+
Application tests check the integration of all the different layers of the
328+
application (from the routing to the views). They are no different from unit tests
329+
or integration tests as far as PHPUnit is concerned, but they have a very specific
330+
workflow:
331+
332+
* Make a request;
333+
* Click on a link or submit a form;
334+
* Test the response;
335+
* Rinse and repeat.
336+
337+
Before creating your first test, install the ``symfony/test-pack`` which
338+
requires multiple packages providing some of the utilities used in the
339+
tests:
340+
341+
.. code-block:: terminal
342+
343+
$ composer require --dev symfony/test-pack
344+
345+
346+
Write Your First Application Test
347+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
371348

372-
Functional tests are PHP files that typically live in the ``tests/Controller``
349+
Application tests are PHP files that typically live in the ``tests/Controller``
373350
directory of your application. If you want to test the pages handled by your
374351
``PostController`` class, start by creating a new ``PostControllerTest.php``
375352
file that extends a special ``WebTestCase`` class.
@@ -393,17 +370,6 @@ As an example, a test could look like this::
393370
}
394371
}
395372

396-
.. tip::
397-
398-
To run your functional tests, the ``WebTestCase`` class needs to know which
399-
is the application kernel to bootstrap it. The kernel class is usually
400-
defined in the ``KERNEL_CLASS`` environment variable (included in the
401-
default ``.env.test`` file provided by Symfony):
402-
403-
If your use case is more complex, you can also override the
404-
``createKernel()`` or ``getKernelClass()`` methods of your functional test,
405-
which take precedence over the ``KERNEL_CLASS`` env var.
406-
407373
In the above example, you validated that the HTTP response was successful. The
408374
next step is to validate that the page actually contains the expected content.
409375
The ``createClient()`` method returns a client, which is like a browser that
@@ -488,7 +454,7 @@ returns a ``Crawler`` instance.
488454

489455
.. tip::
490456

491-
Hardcoding the request URLs is a best practice for functional tests. If the
457+
Hardcoding the request URLs is a best practice for application tests. If the
492458
test generates URLs using the Symfony router, it won't detect any change
493459
made to the application URLs which may impact the end users.
494460

@@ -704,7 +670,7 @@ You can also override HTTP headers on a per request basis::
704670
Reporting Exceptions
705671
....................
706672

707-
Debugging exceptions in functional tests may be difficult because by default
673+
Debugging exceptions in application tests may be difficult because by default
708674
they are caught and you need to look at the logs to see which exception was
709675
thrown. Disabling catching of exceptions in the test client allows the exception
710676
to be reported by PHPUnit::
@@ -1030,7 +996,6 @@ Learn more
1030996

1031997
.. _`PHPUnit`: https://phpunit.de/
1032998
.. _`documentation`: https://phpunit.readthedocs.io/
1033-
.. _`PHPUnit Bridge component`: https://symfony.com/components/PHPUnit%20Bridge
1034999
.. _`Writing Tests for PHPUnit`: https://phpunit.readthedocs.io/en/stable/writing-tests-for-phpunit.html
10351000
.. _`unit test`: https://en.wikipedia.org/wiki/Unit_testing
10361001
.. _`$_SERVER`: https://www.php.net/manual/en/reserved.variables.server.php

0 commit comments

Comments
 (0)