Integrating Symfony with PHPUnit framework

In this article, we shall find the steps to integrate Symfony with an independent library called “PHPUnit” for testing purpose and func. Since we are working on PHP development, let’s discuss the framework called Symfony, PHPUnit.

Before we are going to the integration extensively, let’s see what and why we actually need “Software Testing”.

What is Software Testing:

Software testing is the process of executing the program especially to find the bugs.

Need for Testing:

Testing makes a product more reliable and efficient. There is a need to deliver a product without any bugs which will give a great assurance about quality.

  1. It should have a good quality.
  2. And also there is a necessary to check whether the product meets the client’s requirement and also the same time it should satisfy the customer needs.
  3. The good product should be user-friendly.

Simply we can say that testing help in validating and verifying the product. We have so many types of testing. But unit testing is the base for all the other testing types. It will be done by developers after completing the coding part of the small unit.

But it’s somewhat difficult to write testing manually and running through each of them. We would have definitely missed some scenarios and test cases which lead to getting a bad impression from the client. Most of the manual testers would have gone through the problem at least once. Humans can make mistakes. But tools can never be. This is the main reason for migrating from manual testing into automation testing.  It will become enjoyable to write tests if we have tools to automate the processes. This is why we are getting the framework called “phpunit” as a unit testing framework for the PHP language.  

What is PHPUnit

PHPUnit is a unit testing framework for the PHP programming language. It is a programmer-oriented testing framework. It is an instance of the xUnit design for unit testing frameworks. It is used by the developer to test their own code so they can deliver a bug-free product.

PHPUnit 5.7: It is supported on PHP 5.6, PHP 7.0, and PHP 7.1.

PHPUnit 4.8: It is supported on PHP 5.3, PHP 5.4, PHP 5.5, and PHP 5.6.

Installation of PHPUnit:

We can install PHPUnit two ways. The easiest way of obtaining PHPUnit by downloading PHAR that has all bundles into a single file.

1. Installing via PHAR:

PHP Archive(PHAR) have distributed that contains everything you need in order to use PHPUnit.

#This will download phpunit.phar file to the current location.

wget https://phar.phpunit.de/phpunit.phar      

#We must give an execution permission to the user.

chmod +x phpunit.phar           

#If you need to access “PHPUnit” command in all pages we need to move the phpunit.phar file to user’s bin folder.

sudo mv phpunit.phar /usr/local/bin/phpunit

# To check the version run the below command

phpunit –version

We can also immediately use the PHAR after you have downloaded it, of course:

#This will download phpunit.phar file to the current location.

wget https://phar.phpunit.de/phpunit.phar
php phpunit.phar –version

PHPUnit 6.1.0 by Sebastian Bergmann and contributors

2. Installing via composer:

We can install this framework via composer using “composer.json”. Require dependencies should be injected into the “composer.json”. The following code will help in updating the composer:


{
  "require-dev":
{
       "phpunit/phpunit":"3.7.*"
   }

}

After injecting the above code into “composer.json”, composer needs to be updated for getting PHPUnit execution.

The composer can update with the following command:

$ composer update

There we go! Now, PHPUnit has installed and executable for tests with the related path of the file. For example, if the test file called “SampleTest.php” with the path of that file to run the test.

So far, we have understood about why we are doing testing and the installation of unit testing with PHPUnit. Before starting any new project, there is a key decision is to pick the right framework. Many popular languages have their own default framework.  But for PHP there is no single default framework.

Since we are around the development of PHP must know the frameworks such as Symfony, Laravel. Symfony is an open source PHP web development framework that is popular among most developers as it develops a high-end complex web application with minimal cost.

Symfony integration with PHPUnit:

Symfony integrates with PHPUnit (an independent library) to give you a rich testing framework. It can be configured by phpunit.xml.dist file in the root of your application.

For example:


<?xml version="1.0" encoding="UTF-8"?>

<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"

        backupGlobals="false"

        colors="true"

        bootstrap="autoload.php">

   <php>

       <ini name="error_reporting" value="-1" />

   </php>

   <testsuites>

       <testsuite name="Project Test Suite">

           <directory>../src/*/*Bundle/Tests</directory>

           <directory>../src/*/Bundle/*Bundle/Tests</directory>

           <directory>../src/*Bundle/Tests</directory>

       </testsuite>

   </testsuites>

   <filter>

       <whitelist>

           <directory>../src</directory>

           <exclude>

               <directory>../src/*Bundle/Resources</directory>

               <directory>../src/*Bundle/Tests</directory>

               <directory>../src/*/*Bundle/Resources</directory>

               <directory>../src/*/*Bundle/Tests</directory>

               <directory>../src/*/Bundle/*Bundle/Resources</directory>

               <directory>../src/*/Bundle/*Bundle/Tests</directory>

           </exclude>

       </whitelist>

   </filter>

</phpunit>

There are two types of testing.

  1. Unit Testing
  2. Functional Testing

Unit Testing:

Unit test allows testing individual components/class, such as a method in a class called “units”.

Writing Symfony unit tests is not much different than writing PHPUnit unit tests. For example, if you have class in Util/ directory with Calculator:

For example, if you have class in Util/ directory with Calculator:

// src/SampleBundle/Util/Calculator.php

namespace SampleBundle\Util;


class Calculator

{

   public function add($x, $z)

   {

       return $x + $z;

   }

}

Then the test script should be create as CalculatorTest in tests/AppBundle/Util directory:

// tests/SampleBundle/Util/CalculatorTest.php

namespace Tests\SampleBundle\Util;

use SampleBundle\Util\Calculator;

use PHPUnit\Framework\TestCase;


class CalculatorTest extends TestCase

{

   public function testAdd()

   {

       $calc = new Calculator();

       $result = $calc->add(30, 12);

       // assert that your calculator added the numbers correctly!

       $this->assertEquals(42, $result);

   }

}

So the tests/AppBundle directory should be replicate your bundle directory for unit tests. So, if you want test a class inside the src/SampleBundle/Util/ directory, you need to put test file inside the tests/SampleBundle/Util/ directory.

You can run using below commands:

# run all tests of the application

phpunit

# run all tests in the Util directory

phpunit tests/SampleBundle/Util

# run tests for the Calculator class

phpunit tests/SampleBundle/Util/CalculatorTest.php

# run all tests in the Util directory

phpunit tests/SampleBundle/

Output:

phpunit CalculatorTest

PHPUnit 6.1.0 by Sebastian Bergmann and contributors.

..

Time: 206 ms, Memory : 15.25 Mb

OK (2 tests, 2 assertions)

Important Notes:

  • Sebastian Bergmann created PHPUnit.
  • Two dots represents just two tests were run.
  • The green bar saying that our test has passed with the number of tests and assertions.
  • Time: 0 seconds – Time duration is taken to execute the test.

Functional Testing:

The functional test allows testing some of the functionalities to find out the errors before deploying them. This will test many methods and may interact with dependencies like Databases or Web Services. Each test a PHP class that should live in the “tests/” directory of your application.

There is no big difference then unit testing but functional testing have some unique workflow:

  1. Make a request
  2. Test the response
  3. Click on a link or submit a form
  4. Test the response
  5. Rinse and repeat

Let’s see how function testing works with an example. We are going to explain how to do a functional testing with Symfony’s crawler.

After creating a Symfony project named ‘crawling’, create a bundle called “FTestingBundle” which holds the application and test code. Now, we have sufficient components such as Symfony with FTestingBundle, PHPUnit to do functional testing.

Change into the directory of the ‘crawling’ project and run the following command to test all the tests inside of the application:

(current directory)$ phpunit -c app/

When we generate a bundle, a small block of sample test code also gets generated.

So the output will be:

.

Time: 1.97  seconds, Memory: 28.00 Mb

OK (1 test, 1 assertion)

This command shows that app is properly installed and tested.

Let’s start with the new controller and controller action. Create a new file named “CrawlingController.php” under src/Crawling/FtestingBundle/Controller and insert the following code into it with the proper namespace and also include the necessary parent class.

CrawlingController.php


<?php

namespace Crawling\FtestingBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class CrawlingController extends Controller {

public function homeAction() {

   return $this->render('CrawlingFtestingBundle:Crawling:home.html.twig');

}

     

}

?>

We have created a method called homeAction() to render a template called ‘home.html.twig’. Create a template file with the following HTML tags inside.

Home.html.twig


<h1>Crawling Home Page</h1>

<p>Here's our crawling home page.</p>

<p>Please visit <a href="{{ path('crawling_other') }}">this other page</a> too!</p>

Atlast define routes for the controller action in configuration file(config.yml).

crawling_home:

   path: /crawling/home

   defaults: { _controller: CrawlingFtestingBundle:Crawling:home }

Writing Function test:

Test files are stored in bundle’s ‘Tests/Controller’ directory.  Each controller must have it’s own test file. Let’s create a test file ‘CrawlingControllerTest.php’ for a CrawlingController.

CrawlingControllerTest.php


<?php

namespace Crawling\FtestingBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class CrawlingControllerTest extends WebTestCase

{

public function testHome() {

$client = static::createClient();

$crawler = $client->request('GET', '/crawling/home');

$heading = $crawler->filter('h1')->eq(0)->text();

$this->assertEquals('Crawling Home Page', $heading);

 }

 }

?>

WebTestCase class gives us a PHPUnit functionality. The test method has created to test home page. Always have prefix our method name with the word test when created test methods.

We are going to test that HTTP request of our route is working as expected. So, use this $client object to make that HTTP request and begin using the Crawler.

The Crawler:

The Crawler in Symfony allows us to collect the information about the pages of web application and also perform actions like clicking links or submitting forms too. For that purpose, we have defined crawler object by making an HTTP request with the client.  This let us know about our page exists along with the proper HTML and formatting and the controller, template, and route all work as a single unit. The crawler object will contain page’s response. We will test this response to ensure everything is working properly as expected.

  • filter() method to filter the response and select all ‘h1’ elements.
  • eq(0) which selects the element of index 0.
  • text() method returns the text of the particular DOM element we have filtered.
  • assertEquals() method which have the first argument as value and the second argument is the expected one.

We are on the correct track if the content matches. Let’s see what happens with the following command:


$ phpunit -c app/  

Output:

..

Time: 206 ms, Memory: 15.25 Mb

OK (2 tests, 2 assertions)

Conclusion:

The above small examples might be useful for beginners who need to get knowledge on Symfony integration with PHPUnit.  We can test a small application through PHPUnit in an efficient way to deliver a product with good quality.

Want to know more about Symfony? Our Symfony experts at agira technologies can help you.