Testing Twig Extensions The Right Way
In the previous article, I wrote how to improve your application’s response time with lazy Twig extensions. Let’s test them properly now.
Before diving into this story make sure you have already read my story on “how to create a Lazy Twig Extension” or that you understand what it is and how it works.
Our app is fast & furious now, using lazy ArticleTagExtension
that does its job done. Now is the time to unit test it to ensure our app won’t break.
Installing PHPUnit
Official Twig testing framework expects PHPUnit to be installed. In case we don’t have it installed yet (really?) we’re going to quickly fix the issuephp composer.phar req --dev phpunit/phpunit ^8.0
which is going to download a pretty decent version of it.
We’ll add the tests
directory for our tests and quickly update the composer.json
file to tell PHP where our test classes are:
"autoload-dev": {
"psr-4": {
"Test\\App\\": "tests"
}
}
Creating a test suite
There’s a handy PHPUnit test suite class called IntegrationTestCase
that takes the heavy lifting. It’s purpose is to test Twig’s extensions in an isolated environment.
Let’s create the test class in the tests/Twig/Extension
directory:
In its most basic form it requires:
- to return the path to the directory in which the class expects to find “Twig tests” (files matching the
*.test
pattern anywhere in this directory) - to return extensions the “Twig tests” are going to use
A Twig test is supposed to be in the following format:
--TEST--
Describe here what & why is being tested--TEMPLATE--
Twig Template of the test--DATA--
Eval'ed PHP expression to use as the template parameters--EXPECT--
The expected output of parsed "Template" with the "Data"
Since our extension now uses a runtime, the tests require a runtime loader that will load. Let’s modify the test to enable it. I have written a simple implementation of the ArticleRepository
to mock the dependency and rule out database access. You could use mocks, but I prefer solid implementations:
And the most important part, the test itself! A file named tests/Twig/Extension/function/get_tags.test
--TEST--
get_tags function should return a list of tags
--TEMPLATE--
{{ get_tags(tag_count)|join(', ') }}
--DATA--
return [
'tag_count' => 5,
]
--EXPECT--
dogs, cats, pigs, pigeons, monkeys
The variable tag_count
is unnecessary, acts as a showcase of how to use test parameters. If you don’t wish to use any, you can simply leave return []
As soon as we run the tests (the --exclude-group
of legacy
is necessary to avoid an unused test case which would otherwise be reported as “skipped”):
vendor/bin/phpunit --exclude-group=legacy --bootstrap vendor/autoload.php tests
We end up green!
OK (1 test, 2 assertions)
Have any questions? Feel free to hit me up in the comments. The code is available publicly under an MIT license on GitHub. Happy testing!
Psst… want to know how to make use of the “yield” keyword in a real-life scenario? See my other publication.