Skip to content

Commit f62f79c

Browse files
ddeboerdbu
authored andcommitted
Provide test functionality in traits
Fix #202. separate http client from trait Make property and methods private Add traits to docs Reduce levels of inheritance
1 parent cdad036 commit f62f79c

14 files changed

+942
-649
lines changed

doc/includes/symfony-process.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Requires Symfony’s Process component, so make sure to include that in your
2+
project:
3+
4+
.. code-block:: bash
5+
6+
$ composer require symfony/process

doc/proxy-clients.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ Then pass that adapter to the caching proxy client::
6666
$proxyClient = new Varnish($servers, '/baseUrl', $adapter);
6767
// Varnish as example, but also possible for NGINX and Symfony
6868

69+
.. _varnish client:
70+
6971
Varnish Client
7072
~~~~~~~~~~~~~~
7173

doc/symfony-cache-configuration.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,34 @@ but you can customize that in the subscriber constructor::
196196

197197
The custom header is removed before sending the response to the client.
198198

199+
.. _symfony-cache x-debugging:
200+
201+
Debugging
202+
~~~~~~~~~
203+
204+
For the ``assertHit`` and ``assertMiss`` assertions to work, you need to add
205+
debug information in your AppCache. Create the cache kernel with the option
206+
``'debug' => true`` and add the following to your ``AppCache``::
207+
208+
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
209+
{
210+
$response = parent::handle($request, $type, $catch);
211+
212+
if ($response->headers->has('X-Symfony-Cache')) {
213+
if (false !== strpos($response->headers->get('X-Symfony-Cache'), 'miss')) {
214+
$state = 'MISS';
215+
} elseif (false !== strpos($response->headers->get('X-Symfony-Cache'), 'fresh')) {
216+
$state = 'HIT';
217+
} else {
218+
$state = 'UNDETERMINED';
219+
}
220+
$response->headers->set('X-Cache', $state);
221+
}
222+
223+
return $response;
224+
}
225+
226+
The ``UNDETERMINED`` state should never happen. If it does, it means that your
227+
HttpCache is not correctly set into debug mode.
228+
199229
.. _HttpCache: http://symfony.com/doc/current/book/http_cache.html#symfony-reverse-proxy

doc/testing-your-application.rst

Lines changed: 137 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,30 @@ Testing Your Application
44
========================
55

66
This chapter describes how to test your application against your reverse proxy.
7-
8-
The FOSHttpCache library provides base test case classes to help you write
9-
functional tests. This is helpful to test the way your application sets caching
10-
headers and invalidates cached content.
11-
12-
By having your test classes extend one of the test case classes, you get:
13-
14-
* independent tests: all previously cached content is removed in the tests
15-
``setUp`` method. The way this is done depends on which reverse proxy you use;
16-
* an instance of this library’s client that is configured to talk to your
17-
reverse proxy server. See reverse proxy specific sections for details;
18-
* convenience methods for executing HTTP requests to your application:
19-
``$this->getHttpAdapter()`` and ``$this->getResponse()``;
20-
* custom assertions ``assertHit`` and ``assertMiss`` for validating a cache
7+
By running your tests against a live instance of your caching proxy, you can
8+
validate the caching headers that your application sets, and the invalidation
9+
rules that it defines.
10+
11+
The FOSHttpCache library provides traits and base test classes to help you write
12+
functional tests. Using the traits, you can extend your own (or your
13+
framework’s) base test classes. For convenience, you can also extend the
14+
FOSHttpCache base test classes, as they include a sensible set of traits by
15+
default.
16+
17+
By using the traits, you get:
18+
19+
* independent tests: all previously cached content is removed in the test’s
20+
``setUp()`` method;
21+
* an instance of this library’s proxy client that is configured to talk to your
22+
proxy server for invalidation requests;
23+
* a convenience method for executing HTTP requests to your caching proxy:
24+
``$this->getResponse()``;
25+
* custom assertions ``assertHit()`` and ``assertMiss()`` for validating a cache
2126
hit/miss.
2227

28+
Configuration
29+
-------------
30+
2331
The recommended way to configure the test case is by setting constants
2432
in your ``phpunit.xml``. Alternatively, you can override the getter methods.
2533

@@ -85,18 +93,31 @@ You can override getters in your test class in the following way::
8593
}
8694
}
8795

88-
VarnishTestCase
89-
---------------
96+
Traits
97+
------
9098

91-
Configuration
92-
'''''''''''''
99+
Caching Proxy Server Traits
100+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
93101

94-
By default, the ``VarnishTestCase`` starts and stops a Varnish server for you.
95-
Make sure ``symfony/process`` is available in your project:
102+
FOSHttpCache provides three caching proxy traits that:
96103

97-
.. code-block:: bash
104+
* if necessary, start your caching proxy server before running the tests;
105+
* clear any cached content between tests to guarantee test isolation;
106+
* if necessary, stop the caching proxy server after the tests have finished;
107+
* provide ``getProxyClient()``, which returns the right
108+
:doc:`proxy client <proxy-clients>` for your proxy server.
98109

99-
$ composer require symfony/process
110+
You only need to include one of these traits in your test classes. Which one
111+
you need (``VarnishTest``, ``NginxTest`` or ``SymfonyTest``) depends on the
112+
caching proxy server that you use.
113+
114+
VarnishTest Trait
115+
"""""""""""""""""
116+
117+
.. include:: includes/symfony-process.rst
118+
119+
Then configure the following parameters. The web server hostname and path to
120+
your VCL file are required.
100121

101122
Then set your Varnish configuration (VCL) file. Configuration is handled either
102123
by overwriting the getter or by defining a PHP constant. You can set the
@@ -106,6 +127,7 @@ configuration parameters are:
106127
======================= ========================= ================================================== ===========================================
107128
Constant Getter Default Description
108129
======================= ========================= ================================================== ===========================================
130+
``WEB_SERVER_HOSTNAME`` ``getHostName()`` hostname your application can be reached at
109131
``VARNISH_FILE`` ``getConfigFile()`` your Varnish configuration (VCL) file
110132
``VARNISH_BINARY`` ``getBinary()`` ``varnishd`` your Varnish binary
111133
``VARNISH_PORT`` ``getCachingProxyPort()`` ``6181`` port Varnish listens on
@@ -134,54 +156,31 @@ For the `assertHit` and `assertMiss` assertions to work, you need to add a
134156
:ref:`custom X-Cache header <varnish_debugging>` to responses served
135157
by your Varnish.
136158

137-
NginxTestCase
138-
-------------
139-
140-
Configuration
141-
'''''''''''''
159+
NginxTest Trait
160+
"""""""""""""""
142161

143-
By default, the ``NginxTestCase`` starts and stops the NGINX server for you and
144-
deletes all cached contents. Make sure ``symfony/process`` is available in your
145-
project:
162+
.. include:: includes/symfony-process.rst
146163

147-
.. code-block:: bash
148-
149-
$ composer require symfony/process
150-
151-
You have to set your NGINX configuration file. All available configuration
152-
parameters are shown below.
164+
Then configure the following parameters. The web server hostname and path to
165+
your NGINX configuration file are required.
153166

154167
======================= ========================= ================================================ ===========================================
155168
Constant Getter Default Description
156169
======================= ========================= ================================================ ===========================================
170+
``WEB_SERVER_HOSTNAME`` ``getHostName()`` hostname your application can be reached at
157171
``NGINX_FILE`` ``getConfigFile()`` your NGINX configuration file
158172
``NGINX_BINARY`` ``getBinary()`` ``nginx`` your NGINX binary
159173
``NGINX_PORT`` ``getCachingProxyPort()`` ``8088`` port NGINX listens on
160174
``NGINX_CACHE_PATH`` ``getCacheDir()`` ``sys_get_temp_dir()`` + ``/foshttpcache-nginx`` directory to use for cache
161175
Must match `proxy_cache_path` directive in
162176
your configuration file.
163-
``WEB_SERVER_HOSTNAME`` ``getHostName()`` hostname your application can be reached at
164177
======================= ========================= ================================================ ===========================================
165178

166-
Enable Assertions
167-
'''''''''''''''''
179+
SymfonyTest Trait
180+
"""""""""""""""""
168181

169-
For the `assertHit` and `assertMiss` assertions to work, you need to add a
170-
:ref:`custom X-Cache header <nginx_debugging>` to responses served
171-
by your Nginx.
172-
173-
SymfonyTestCase
174-
---------------
175-
176-
This test case helps to test invalidation requests with a symfony application
177-
running the Symfony HttpCache and invalidating its cache folder to get reliable
178-
tests.
179-
180-
The ``SymfonyTestCase`` does automatically start a web server. It is assumed
181-
that the web server you run for the application has the HttpCache integrated.
182-
183-
Configuration
184-
'''''''''''''
182+
It is assumed that the web server you run for the application has the HttpCache
183+
integrated.
185184

186185
======================= ========================= ================================================ ===========================================
187186
Constant Getter Default Description
@@ -194,59 +193,92 @@ Constant Getter Default
194193
running PHPUnit.
195194
======================= ========================= ================================================ ===========================================
196195

197-
Enable Assertions
198-
'''''''''''''''''
196+
HttpCaller Trait
197+
~~~~~~~~~~~~~~~~
198+
199+
Provides your tests with a ``getResponse`` method, which retrieves a URI from
200+
your application through a real HTTP call that goes through the HTTP caching
201+
proxy::
199202

200-
For the `assertHit` and `assertMiss` assertions to work, you need to add debug
201-
information in your AppCache. Create the cache kernel with the option
202-
``'debug' => true`` and add the following to your ``AppCache``::
203+
use FOS\HttpCache\Test\HttpCaller;
203204

204-
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
205+
class YourTest extends \PHPUnit_Framework_TestCase
205206
{
206-
$response = parent::handle($request, $type, $catch);
207-
208-
if ($response->headers->has('X-Symfony-Cache')) {
209-
if (false !== strpos($response->headers->get('X-Symfony-Cache'), 'miss')) {
210-
$state = 'MISS';
211-
} elseif (false !== strpos($response->headers->get('X-Symfony-Cache'), 'fresh')) {
212-
$state = 'HIT';
213-
} else {
214-
$state = 'UNDETERMINED';
215-
}
216-
$response->headers->set('X-Cache', $state);
207+
public function testCachingHeaders()
208+
{
209+
// Get some response from your application
210+
$response = $this->getResponse('/path');
211+
212+
// Optionally with request headers and a custom method
213+
$response = $this->getResponse('/path', ['Accept' => 'text/json'], 'PUT');
217214
}
215+
}
218216

219-
return $response;
217+
CacheAssertions Trait
218+
~~~~~~~~~~~~~~~~~~~~~
219+
220+
Provides cache hit/miss assertions to your tests. To enable the these
221+
``assertHit`` and ``assertMiss`` assertions, you need to configure your caching
222+
server to set an `X-Cache` header with the cache status:
223+
224+
* :ref:`Varnish <varnish_debugging>`
225+
* :ref:`NGINX <nginx_debugging>`
226+
* :ref:`Symfony HttpCache <symfony-cache x-debugging>`
227+
228+
Then use the assertions as follows::
229+
230+
use FOS\HttpCache\Test\CacheAssertions;
231+
232+
class YourTest extends \PHPUnit_Framework_TestCase
233+
{
234+
public function testCacheHitOrMiss()
235+
{
236+
// Assert the application response is a cache miss
237+
$this->assertMiss($response);
238+
239+
// Or assert it is a hit
240+
$this->assertHit($response);
241+
}
220242
}
221243

222-
The ``UNDETERMINED`` state should never happen. If it does, it means that your
223-
HttpCache is not correctly set into debug mode.
244+
Base Classes for Convenience
245+
----------------------------
246+
247+
If you prefer, you can extend your test classes from ``VarnishTestCase``,
248+
``NginxTestCase`` or ``SymfonyTestCase``. The appropriate traits will then
249+
automatically be included.
224250

225251
Usage
226252
-----
227253

228254
This example shows how you can test whether the caching headers your
229-
application sets influence Varnish as you expect them to::
255+
application sets influence your caching proxy as you expect them to::
230256

231-
use FOS\HttpCache\Test\VarnishTestCase;
257+
use FOS\HttpCache\Test\CacheAssertions;
258+
use FOS\HttpCache\Test\HttpCaller;
259+
use FOS\HttpCache\Test\VarnishTest;
260+
// or FOS\HttpCache\Test\NginxTest;
261+
// or FOS\HttpCache\Test\SymfonyTest;
232262

233-
class YourFunctionalTest extends VarnishTestCase
263+
class YourTest extends \PHPUnit_Framework_TestCase
234264
{
235265
public function testCachingHeaders()
236266
{
237-
// Varnish is restarted, so you don’t have to worry about previously
238-
// cached content. Before continuing, the VarnishTestCase waits for
239-
// Varnish to become available.
267+
// The caching proxy is (re)started, so you don’t have to worry
268+
// about previously cached content. Before continuing, the
269+
// VarnishTest/ NginxTest trait waits for the caching proxy to
270+
// become available.
240271

241-
// Retrieve an URL from your application
272+
// Retrieve a URL from your application
242273
$response = $this->getResponse('/your/resource');
243274

244275
// Assert the response was a cache miss (came from the backend
245276
// application)
246277
$this->assertMiss($response);
247278

248-
// Assume the URL /your/resource sets caching headers. If we retrieve
249-
// it again, we should have a cache hit (response delivered by Varnish):
279+
// Assume the URL /your/resource sets caching headers. If we
280+
// retrieve it again, we should have a cache hit (response delivered
281+
// by the caching proxy):
250282
$response = $this->getResponse('/your/resource');
251283
$this->assertHit($response);
252284
}
@@ -255,26 +287,34 @@ application sets influence Varnish as you expect them to::
255287
This example shows how you can test whether your application purges content
256288
correctly::
257289

258-
public function testCachePurge()
290+
use FOS\HttpCache\Test\CacheAssertions;
291+
use FOS\HttpCache\Test\HttpCaller;
292+
use FOS\HttpCache\Test\VarnishTest;
293+
// or FOS\HttpCache\Test\NginxTest;
294+
// or FOS\HttpCache\Test\SymfonyTest;
295+
296+
class YourTest extends \PHPUnit_Framework_TestCase
259297
{
260-
// Again, Varnish is restarted, so your test is independent from
261-
// other tests
298+
public function testCachePurge()
299+
{
300+
// Again, the caching proxy is restarted, so your test is independent
301+
// from other tests
262302

263-
$url = '/blog/articles/1';
303+
$url = '/blog/articles/1';
264304

265-
// First request must be a cache miss
266-
$this->assertMiss($this->getResponse($url));
305+
// First request must be a cache miss
306+
$this->assertMiss($this->getResponse($url));
267307

268-
// Next requests must be a hit
269-
$this->assertHit($this->getResponse($url));
308+
// Next requests must be a hit
309+
$this->assertHit($this->getResponse($url));
270310

271-
// Purge
272-
$this->varnish->purge('/blog/articles/1');
311+
// Purge
312+
$this->getProxyClient()->purge('/blog/articles/1');
273313

274-
// First request after must again be a miss
275-
$this->assertMiss($this->getResponse($url));
314+
// First request after must again be a miss
315+
$this->assertMiss($this->getResponse($url));
316+
}
276317
}
277318

278-
Tests for Nginx look the same but extend the NginxTestCase.
279319
For more ideas, see this library’s functional tests in the
280320
:source:`tests/Functional/` directory.

0 commit comments

Comments
 (0)