Twig Template Unit Testing

Testing for syntax error within twig templates:

You can use the command line to test on all twig templates into one Bundle by using:

php app/console twig:lint @name of Bundle

Example:

php app/console twig:lint @AcmeDemoBundle

The result will be:

if there isn't any syntax error:

OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/layout.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Demo/contact.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Demo/index.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Secured/layout.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Secured/login.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Secured/helloadmin.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Secured/hello.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Welcome/index.html.twig

If there is a syntax error, it will detect line which syntax error in it and reason for Syntax error:

OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/layout.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig
KO in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Demo/contact.html.twig (line 6)
   4      
   5      {% block content %}
>> 6          <form action="{{ ath('_demo_contact') }}" method="POST" id="contact_form">
>> The function "ath" does not exist. Did you mean "path", "logout_path" 
   7              {{ form_errors(form) }}
   8      
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Demo/index.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Secured/layout.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Secured/login.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Secured/helloadmin.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Secured/hello.html.twig
OK in /var/www/SymBlog/src/Acme/DemoBundle/Resources/views/Welcome/index.html.twig

In addition to verifying the structural and syntactical correctness of your Twig template files by linting them, you can also unit test the logic of your Twig templates.

For example, you can verify the correct behaviour of an if-elseif-else-endif construct, and you can do so in isolation, that is, without the need to go through controllers with all their dependencies.

Have a look at https://github.com/journeymonitor/control/blob/2645c69/src/AppBundle/Resources/views/testcases/_testresults-overview-testresult-label.html.twig. It's a very simple template, but it does have some amount of behaviour - depending on the value of testresult.exitCode, different label names must be output.

At https://github.com/journeymonitor/control/blob/bc42e78/tests/AppBundle/Resources/views/testcases/_testresults-overview-testresult-label.html.twig.test.php, you can see the unit test case for this template.

The test case sets up a new Twig_Environment, which enables you to load the Twig template file and render it with different Testresult objects passed in as a parameter. The result of the render operation can then be asserted as in any other PHPUnit test:

$loader = new Twig_Loader_Filesystem(__DIR__ . '/../../../../../src/AppBundle/Resources/views/testcases/');
$twig = new Twig_Environment($loader, array(
    'cache' => '/var/tmp/journeymonitor-twig-tests-cache',
));
$template = $twig->loadTemplate('_testresults-overview-testresult-label.html.twig');

$testresult = new \AppBundle\Entity\Testresult();
$testresult->setExitCode(0);

$this->assertSame('success', $template->render(['testresult' => $testresult]));

Note the shell commands on line 8 and 9 - the Twig environment caches its template files, and in order to have reliable tests, you need to ensure that the cache location is wiped before each test run:

`rm -rf /var/tmp/journeymonitor-twig-tests-cache`;
`mkdir -p /var/tmp/journeymonitor-twig-tests-cache`;

Use symfony to test an individual twig file like this:

./app/console twig:lint /yourproject/yourtwigs/views/yourtwig.html.twig

Result if OK:

OK in /yourproject/yourtwigs/views/yourtwig.html.twig

Result if not OK (I added a curly brace where it didn't belong):

/yourproject/yourtwigs/views/yourtwig.html.twig (line 2)
   1      {% include 'YourBundle:Includes:jquery.html.twig' %} 
>> 2      {{% include 'YourBundle:Includes:datatables.html.twig' %}
>> Unexpected "}" 
   3      <script>
   4      $(document).ready(function() 

Inside a WebTestCase (extension of a phpunit TestCase since Symfony 2.0) / KernelTestCase (extension of phpunit TestCase since Symfony 2.5)

    $twig = self::$kernel->getContainer()->get('twig');
    $html = $twig->render('AppBundle::app/something.html.twig', ['content' => 'I am some variable value']);
    self::assertEquals($html, $response->getContent());