Skip to content

Commit 8e59931

Browse files
committed
Merge branch '2.7' into 2.8
2 parents 778a7f9 + 0e56ff9 commit 8e59931

File tree

4 files changed

+252
-1
lines changed

4 files changed

+252
-1
lines changed

Diff for: components/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ The Components
2323
http_kernel/index
2424
intl
2525
options_resolver
26+
phpunit_bridge
2627
process
2728
property_access/index
2829
routing/index

Diff for: components/map.rst.inc

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* :doc:`/components/asset/introduction`
66

77
* :doc:`/components/browser_kit/index`
8-
8+
99
* :doc:`/components/browser_kit/introduction`
1010

1111
* :doc:`/components/class_loader/index`
@@ -116,6 +116,10 @@
116116

117117
* :doc:`/components/options_resolver`
118118

119+
* **PHPUnitBridge**
120+
121+
* :doc:`/components/phpunit_bridge`
122+
119123
* **Process**
120124

121125
* :doc:`/components/process`

Diff for: components/phpunit_bridge.rst

+246
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
.. index::
2+
single: PHPUnitBridge
3+
single: Components; PHPUnitBridge
4+
5+
The PHPUnit Bridge
6+
==================
7+
8+
The PHPUnit Bridge provides utilities to report legacy tests and usage of
9+
deprecated code and a helper for time-sensitive tests.
10+
11+
It comes with the following features:
12+
13+
* Forces the tests to use a consistent locale (``C``);
14+
15+
* Auto-register ``class_exists`` to load Doctrine annotations (when used);
16+
17+
* It displays the whole list of deprecated features used in the application;
18+
19+
* Displays the stack trace of a deprecation on-demand;
20+
21+
* Provides a ``ClockMock`` helper class for time-sensitive tests.
22+
23+
.. versionadded:: 2.7
24+
The PHPUnit Bridge was introduced in Symfony 2.7. It is however possible to
25+
install the bridge in any Symfony application (even 2.3).
26+
27+
Installation
28+
------------
29+
30+
You can install the component in 2 different ways:
31+
32+
* :doc:`Install it via Composer </components/using_components>`
33+
(``symfony/phpunit-bridge`` on `Packagist`_); as a dev dependency;
34+
35+
* Use the official Git repository (https://github.com/symfony/phpunit-bridge).
36+
37+
.. include:: /components/require_autoload.rst.inc
38+
39+
Usage
40+
-----
41+
42+
Once the component installed, it automatically registers a
43+
`PHPUnit event listener`_ which in turn registers a `PHP error handler`_
44+
called :class:`Symfony\\Bridge\\PhpUnit\\DeprecationErrorHandler`. After
45+
running your PHPUnit tests, you will get a report similar to this one:
46+
47+
.. image:: /images/components/phpunit_bridge/report.png
48+
49+
The summary includes:
50+
51+
**Unsilenced**
52+
Reports deprecation notices that were triggered without the recommended
53+
`@-silencing operator`_.
54+
55+
**Legacy**
56+
Deprecation notices denote tests that explicitly test some legacy features.
57+
58+
**Remaining/Other**
59+
Deprecation notices are all other (non-legacy) notices, grouped by message,
60+
test class and method.
61+
62+
Trigger Deprecation Notices
63+
---------------------------
64+
65+
Deprecation notices can be triggered by using::
66+
67+
@trigger_error('Your deprecation message', E_USER_DEPRECATED);
68+
69+
Without the `@-silencing operator`_, users would need to opt-out from deprecation
70+
notices. Silencing by default swaps this behavior and allows users to opt-in
71+
when they are ready to cope with them (by adding a custom error handler like the
72+
one provided by this bridge). When not silenced, deprecation notices will appear
73+
in the **Unsilenced** section of the deprecation report.
74+
75+
Mark Tests as Legacy
76+
--------------------
77+
78+
There are four ways to mark a test as legacy:
79+
80+
* (**Recommended**) Add the ``@group legacy`` annotation to its class or method;
81+
82+
* Make its class name start with the ``Legacy`` prefix;
83+
84+
* Make its method name start with ``testLegacy`` instead of ``test``;
85+
86+
* Make its data provider start with ``provideLegacy`` or ``getLegacy``.
87+
88+
Configuration
89+
-------------
90+
91+
In case you need to inspect the stack trace of a particular deprecation
92+
triggered by your unit tests, you can set the ``SYMFONY_DEPRECATIONS_HELPER``
93+
`environment variable`_ to a regular expression that matches this deprecation's
94+
message, enclosed with ``/``. For example, with:
95+
96+
.. code-block:: xml
97+
98+
<!-- http://phpunit.de/manual/4.1/en/appendixes.configuration.html -->
99+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
100+
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
101+
>
102+
103+
<!-- ... -->
104+
105+
<php>
106+
<server name="KERNEL_DIR" value="app/" />
107+
<env name="SYMFONY_DEPRECATIONS_HELPER" value="/foobar/" />
108+
</php>
109+
</phpunit>
110+
111+
PHPUnit_ will stop your test suite once a deprecation notice is triggered whose
112+
message contains the ``"foobar"`` string.
113+
114+
Making Tests Fail
115+
-----------------
116+
117+
By default, any non-legacy-tagged or any non-`@-silenced`_ deprecation notices will
118+
make tests fail. Alternatively, setting ``SYMFONY_DEPRECATIONS_HELPER`` to an
119+
arbitrary value (ex: ``320``) will make the tests fails only if a higher number
120+
of deprecation notices is reached (``0`` is the default value). You can also set
121+
the value ``"weak"`` which will make the bridge ignore any deprecation notices.
122+
This is useful to projects that must use deprecated interfaces for backward
123+
compatibility reasons.
124+
125+
Time-sensitive Tests
126+
--------------------
127+
128+
Use Case
129+
~~~~~~~~
130+
131+
If you have this kind of time-related tests::
132+
133+
use Symfony\Component\Stopwatch\Stopwatch;
134+
135+
class MyTest extends \PHPUnit_Framework_TestCase
136+
{
137+
public function testSomething()
138+
{
139+
$stopwatch = new Stopwatch();
140+
141+
$stopwatch->start();
142+
sleep(10);
143+
$duration = $stopwatch->stop();
144+
145+
$this->assertEquals(10, $duration);
146+
}
147+
}
148+
149+
You used the :doc:`Symfony Stopwatch Component </components/stopwatch>` to
150+
calculate the duration time of your process, here 10 seconds. However, depending
151+
on the load of the server your the processes running on your local machine, the
152+
``$duration`` could for example be `10.000023s` instead of `10s`.
153+
154+
This kind of tests are called transient tests: they are failing randomly
155+
depending on spurious and external circumstances. They are often cause trouble
156+
when using public continuous integration services like `Travis CI`_.
157+
158+
Clock Mocking
159+
~~~~~~~~~~~~~
160+
161+
The :class:`Symfony\\Bridge\\PhpUnit\\ClockMock` class provided by this bridge
162+
allows you to mock the PHP's built-in time functions ``time()``,
163+
``microtime()``, ``sleep()`` and ``usleep()``.
164+
165+
To use the ``ClockMock`` class in your test, you can:
166+
167+
* (**Recommended**) Add the ``@group time-sensitive`` annotation to its class or
168+
method;
169+
170+
* Register it manually by calling ``ClockMock::register(__CLASS__)`` and
171+
``ClockMock::withClockMock(true)`` before the test and
172+
``ClockMock::withClockMock(false)`` after the test.
173+
174+
As a result, the following is guarenteed to work and is no longer a transient
175+
test::
176+
177+
use Symfony\Component\Stopwatch\Stopwatch;
178+
179+
/**
180+
* @group time-sensitive
181+
*/
182+
class MyTest extends \PHPUnit_Framework_TestCase
183+
{
184+
public function testSomething()
185+
{
186+
$stopwatch = new Stopwatch();
187+
188+
$stopwatch->start();
189+
sleep(10);
190+
$duration = $stopwatch->stop();
191+
192+
$this->assertEquals(10, $duration);
193+
}
194+
}
195+
196+
And that's all!
197+
198+
.. tip::
199+
200+
An added bonus of using the ``ClockMock`` class is that time passes
201+
instantly. Using PHP's ``sleep(10)`` will make your test wait for 10
202+
actual seconds (more or less). In contrast, the ``ClockMock`` class
203+
advances the internal clock the given number of seconds without actually
204+
waiting that time, so your test will execute 10 seconds faster.
205+
206+
Troubleshooting
207+
~~~~~~~~~~~~~~~
208+
209+
The ``@group time-sensitive`` works "by convention" and assumes that the
210+
namespace of the tested class can be obtained just by removing the ``\Tests\``
211+
part from the test namespace. I.e. that if the your test case fully-qualified
212+
class name (FQCN) is ``App\Tests\Watch\DummyWatchTest``, it assumes the tested
213+
class FQCN is ``App\Watch\DummyWatch``.
214+
215+
If this convention doesn't work for your application, you can also configure
216+
the mocked namespaces in the ``phpunit.xml`` file, as done for example in the
217+
:doc:`HttpKernel Component </components/http_kernel/introduction>`:
218+
219+
.. code-block:: xml
220+
221+
<!-- http://phpunit.de/manual/4.1/en/appendixes.configuration.html -->
222+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
223+
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
224+
>
225+
226+
<!-- ... -->
227+
228+
<listeners>
229+
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener">
230+
<arguments>
231+
<array>
232+
<element><string>Symfony\Component\HttpFoundation</string></element>
233+
</array>
234+
</arguments>
235+
</listener>
236+
</listeners>
237+
</phpunit>
238+
239+
.. _PHPUnit: https://phpunit.de
240+
.. _`PHPUnit event listener`: https://phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener
241+
.. _`PHP error handler`: http://php.net/manual/en/book.errorfunc.php
242+
.. _`environment variable`: https://phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.php-ini-constants-variables
243+
.. _Packagist: https://packagist.org/packages/symfony/phpunit-bridge
244+
.. _`@-silencing operator`: http://php.net/manual/en/language.operators.errorcontrol.php
245+
.. _`@-silenced`: http://php.net/manual/en/language.operators.errorcontrol.php
246+
.. _`Travis CI`: https://travis-ci.com/

Diff for: images/components/phpunit_bridge/report.png

46.6 KB
Loading

0 commit comments

Comments
 (0)