Skip to content

Commit 4decfa9

Browse files
committed
feature #6273 [PHPUnit bridge] Add documentation for the component (theofidry)
This PR was submitted for the 2.3 branch but it was merged into the 2.7 branch instead (closes #6273). Discussion ---------- [PHPUnit bridge] Add documentation for the component | Q | A | ------------- | --- | Doc fix? | no | New docs? | yes | Applies to | all | Fixed tickets | #5059 First draft of the doc. I'm not hyper familiar with the component so I may have overlooked a feature. Also I kind of find the name off: *PHPUnit Bridge*, it's not about a bridge, it's about deprecation. Bridge is the technical solution to bring it, it does not reflect what the component does. Commits ------- 6a1d886 [PHPUnit bridge] Add documentation for the component
2 parents 29567b1 + 6a1d886 commit 4decfa9

File tree

4 files changed

+248
-1
lines changed

4 files changed

+248
-1
lines changed

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

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`
@@ -115,6 +115,10 @@
115115

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

118+
* **PHPUnitBridge**
119+
120+
* :doc:`/components/phpunit_bridge`
121+
118122
* **Process**
119123

120124
* :doc:`/components/process`

components/phpunit_bridge.rst

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

0 commit comments

Comments
 (0)