@@ -15,67 +15,57 @@ Symfony integrates with an independent library called `PHPUnit`_ to give you a
15
15
rich testing framework. This article won't cover PHPUnit itself, which has its
16
16
own excellent `documentation `_.
17
17
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:
20
19
21
20
.. code-block :: terminal
22
21
23
- $ composer require --dev symfony /phpunit-bridge
22
+ $ composer require --dev phpunit /phpunit
24
23
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:
28
25
29
26
.. code-block :: terminal
30
27
31
- $ ./bin/phpunit
28
+ $ ./vendor/ bin/phpunit
32
29
33
30
.. note ::
34
31
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.
40
35
41
36
Each test is a PHP class that should live in the ``tests/ `` directory of
42
37
your application. If you follow this rule, then you can run all of your
43
38
application's tests with the same command as before.
44
39
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.
52
41
53
42
Types of Tests
54
43
--------------
55
44
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
+
56
50
`Unit Tests `_
57
51
These tests ensure that *individual * units of source code (e.g. a single
58
52
class) behave as intended.
59
53
60
54
`Integration Tests `_
61
55
These tests test a combination of classes and commonly interact with
62
56
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 *.
64
58
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
67
61
make HTTP requests and test that the response is as expected.
68
62
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
-
73
63
Unit Tests
74
64
----------
75
65
76
66
A `unit test `_ ensures that individual units of source code (e.g. a single
77
67
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
79
69
standard PHPUnit unit tests. You can learn about it in the PHPUnit
80
70
documentation: `Writing Tests for PHPUnit `_.
81
71
@@ -85,103 +75,66 @@ of your application for unit tests. So, if you're testing a class in the
85
75
Autoloading is automatically enabled via the ``vendor/autoload.php `` file
86
76
(as configured by default in the ``phpunit.xml.dist `` file).
87
77
88
- You can run tests using the ``bin/phpunit `` command:
78
+ You can run tests using the ``./vendor/ bin/phpunit `` command:
89
79
90
80
.. code-block :: terminal
91
81
92
82
# run all tests of the application
93
- $ php bin/phpunit
83
+ $ php ./vendor/ bin/phpunit
94
84
95
85
# run all tests in the Util/ directory
96
- $ php bin/phpunit tests/Util
86
+ $ php ./vendor/ bin/phpunit tests/Util
97
87
98
88
# run tests for the Calculator class
99
- $ php bin/phpunit tests/Util/CalculatorTest.php
89
+ $ php ./vendor/ bin/phpunit tests/Util/CalculatorTest.php
100
90
101
91
Integration Tests
102
92
-----------------
103
93
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.
105
97
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
122
99
public services and the non-removed :ref: `private services <container-public >`
123
100
services::
124
101
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;
129
104
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;
142
107
108
+ class AcmeServiceTest extends KernelTestCase
109
+ {
143
110
public function testSomething()
144
111
{
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();
148
114
149
- // $somePrivateService = $specialContainer->get('the-service-ID');
115
+ $container = self::$container;
116
+ $someService = $container->get(AcmeService::class);
150
117
151
- // ...
118
+ $result = $someService->something();
119
+ $this->assertTrue($result);
152
120
}
121
+ }
153
122
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 ::
176
124
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):
178
129
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.
180
133
181
134
Set-up your Test Environment
182
135
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
183
136
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
185
138
``test `` environment. Since Symfony loads the ``config/packages/test/*.yaml ``
186
139
in the ``test `` environment, you can tweak any of your application's settings
187
140
specifically for testing.
@@ -229,7 +182,7 @@ You can also use a different environment entirely, or override the default
229
182
debug mode (``true ``) by passing each as options to the ``createClient() ``
230
183
method::
231
184
232
- $client = static::createClient ([
185
+ self::bootKernel ([
233
186
'environment' => 'my_test_env',
234
187
'debug' => false,
235
188
]);
@@ -293,7 +246,7 @@ that ensures that each test is run with the same unmodified database:
293
246
294
247
$ composer require --dev dama/doctrine-test-bundle
295
248
296
- Now, enable it as a PHPUnit extension or listener :
249
+ Now, enable it as a PHPUnit extension:
297
250
298
251
.. code-block :: xml
299
252
@@ -366,10 +319,34 @@ Empty the database and reload *all* the fixture classes with:
366
319
367
320
For more information, read the `DoctrineFixturesBundle documentation `_.
368
321
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
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
371
348
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 ``
373
350
directory of your application. If you want to test the pages handled by your
374
351
``PostController `` class, start by creating a new ``PostControllerTest.php ``
375
352
file that extends a special ``WebTestCase `` class.
@@ -393,17 +370,6 @@ As an example, a test could look like this::
393
370
}
394
371
}
395
372
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
-
407
373
In the above example, you validated that the HTTP response was successful. The
408
374
next step is to validate that the page actually contains the expected content.
409
375
The ``createClient() `` method returns a client, which is like a browser that
@@ -488,7 +454,7 @@ returns a ``Crawler`` instance.
488
454
489
455
.. tip ::
490
456
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
492
458
test generates URLs using the Symfony router, it won't detect any change
493
459
made to the application URLs which may impact the end users.
494
460
@@ -704,7 +670,7 @@ You can also override HTTP headers on a per request basis::
704
670
Reporting Exceptions
705
671
....................
706
672
707
- Debugging exceptions in functional tests may be difficult because by default
673
+ Debugging exceptions in application tests may be difficult because by default
708
674
they are caught and you need to look at the logs to see which exception was
709
675
thrown. Disabling catching of exceptions in the test client allows the exception
710
676
to be reported by PHPUnit::
@@ -1030,7 +996,6 @@ Learn more
1030
996
1031
997
.. _`PHPUnit` : https://phpunit.de/
1032
998
.. _`documentation` : https://phpunit.readthedocs.io/
1033
- .. _`PHPUnit Bridge component` : https://symfony.com/components/PHPUnit%20Bridge
1034
999
.. _`Writing Tests for PHPUnit` : https://phpunit.readthedocs.io/en/stable/writing-tests-for-phpunit.html
1035
1000
.. _`unit test` : https://en.wikipedia.org/wiki/Unit_testing
1036
1001
.. _`$_SERVER` : https://www.php.net/manual/en/reserved.variables.server.php
0 commit comments