Skip to content

Commit 98d8755

Browse files
committed
[#6564] Revert doc removal in 2.8
1 parent 6b7b057 commit 98d8755

File tree

1 file changed

+117
-1
lines changed

1 file changed

+117
-1
lines changed

components/phpunit_bridge.rst

+117-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ The PHPUnit Bridge
66
==================
77

88
The PHPUnit Bridge provides utilities to report legacy tests and usage of
9-
deprecated code.
9+
deprecated code and a helper for time-sensitive tests.
1010

1111
It comes with the following features:
1212

@@ -18,6 +18,8 @@ It comes with the following features:
1818

1919
* Displays the stack trace of a deprecation on-demand;
2020

21+
* Provides a ``ClockMock`` helper class for time-sensitive tests.
22+
2123
.. versionadded:: 2.7
2224
The PHPUnit Bridge was introduced in Symfony 2.7. It is however possible to
2325
install the bridge in any Symfony application (even 2.3).
@@ -120,6 +122,120 @@ the value ``"weak"`` which will make the bridge ignore any deprecation notices.
120122
This is useful to projects that must use deprecated interfaces for backward
121123
compatibility reasons.
122124

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+
123239
.. _PHPUnit: https://phpunit.de
124240
.. _`PHPUnit event listener`: https://phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener
125241
.. _`PHP error handler`: http://php.net/manual/en/book.errorfunc.php

0 commit comments

Comments
 (0)