A Definitive Guide to Testing PHP Applications with PHP Unit

A Definitive Guide to Testing PHP Applications with PHP Unit
COMMENTS ()
Tweet

The fact you are on this page clearly shows that you want to unit test your PHP application. If you are still not very convinced on putting efforts into unit tests and would like to have a solid footing on why they matter, read it here: Unit Tests, How to Write Testable Code and Why it Matters

This should be of no surprise for a popular language like PHP to have multiple automated testing frameworks available, but PHP Unit is a clear winner. PHP Unit is a huge open source contribution by Sebastian Bergmann. See it’s Github source code here.

This blog is not a comprehensive documentation of what PHP Unit is and what isn’t. A thorough documentation in multiple languages is already available on the official site. Instead, based on my experience of working with PHP Unit, I try to give an overview of the commonly used features available in PHP Unit, and also put a number of implementation tips to get you started with it.

Choosing your Version of PHP Unit

The PHP Unit home page clearly outlines its major versions, the compatible PHP versions and an official date corresponding to it’s each major version, when the official support has ended or is going to end. Ensure, that you choose the right version of PHP Unit given the PHP version used in your application.

Note: PHP Unit 6 onwards has dropped support for PHP 5.

Adding PHP Unit to your Project

A phar is also available on the official site but Composer, the PHP package manager, makes it effortless to add it to your project.  In your project root, run:

composer require –dev phpunit/phpunit ^7

This will add or modify a previously existing composer.json in your project root, and will add PHP Unit to its require-dev dependencies.

See Versions and Constraints on how to set versions and constraints when adding any package via composer.

Note: If you are directly adding or updating PHP Unit in composer.json, run composer update to reflect required changes.

Running PHP Unit from Command Line

The composer by default installs all of its packages in vendor/bin directory. Given that composer executable is present in your system path, you can execute php unit by: ./vendor/bin/phpunit

A huge range of configurations options can be passed via command line altering test execution flow, test execution paths and output. A complete list of available options can be seen here: The Command-Line Test Runner

Adding an XML Configuration File

The command line options come in very handy when you need to execute a specific test or a test suite, or you want to generate report in some specific format only at a particular time.

But, if you want to customize a lot of default behaviors, and test different test suites, the XML config file is the way to go. Add an XML file phpunit.xml in the root directory and add relevant xml tags to customize the test execution. The complete list of available options can be read here: The XML Configuration

This is a sample phpunit.xml file.

<phpunit
        colors="true"
        convertErrorsToExceptions="true"
        convertNoticesToExceptions="true"
        convertWarningsToExceptions="true"
        stopOnFailure="false"
        bootstrap="vendor/autoload.php">
    <testsuites>
        <testsuite name="HelloWorld PHP">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
</phpunit>

 

Given this config file, PHP Unit will print output in colors if supported by console. It will convert errors, notices and warnings to exceptions. It won’t stop on any test case failure and will execute till the end.

The ‘bootstrap’ attribute ensures that source code and other packages, installed via composer, are loaded before tests are executed. The testsuites tag, gives the test suite name and the directory. So the test files need to be present in the tests/ directory from root for this testsuite to execute.

Writing your First Test

<?php

namespace HelloWorld\Tests;

class MyFirstTest extends \PHPUnit_Framework_TestCase
{

    public function testHelloWorldApp()
    {
        $this->assertEquals(5, 5.0)
    }
}

 

  • The test class is named as <prefix>Test
  • It extends from \PHPUnit_Framework_TestCase
  • All tests are public methods named as test<Suffix>
  • There should be at least one assertion in each test.

Save this file in your tests directory. Execute PHP Unit from command line. Please see the detailed guide on Writing Tests here.

Set Up and Tear down

When you organize multiple test methods into a single class, it’s often the case that you have to initiate common class objects and allocate resources for each of the test cases. And you may also want that each of the test methods in the class runs in segregation with a fresh copy of the objects and resources. PHP Unit provides four methods to avoid code duplication for this task:

  • setUp() – This is executed before each test method
  • tearDown() – Executed after each method. This should only be written to unset variables and resources if the code uses a large number of objects or external resources. Otherwise, the PHP garbage collector will automatically deallocate the memory within sometime.
  • setUpBeforeClass() – This is executed before executing the first method of the class
  • teardownAfterClass() – Same as tearDown(), but executed only after the last method of the class.

For further detail see : Fixtures

Assertions

The key to unit testing is asserting. It’s the assertion that eventually passes or fails a test case. PHP Unit provides a great number of assertions for our use. See them here Assertions.

Such as:

assertEqual/assertNull/assertTrue/assertNan/assertLessThanOrEqual etc.

assertClassHasAttribute/assertContains/assertIsWritable etc.

  • It’s very likely that you ignore a specific assertion method, and instead use some custom logic with assertEquals or assertTrue to achieve the same. Well, it may not cause problems at all but using specific method definitely helps with debugging when the test case fails. For example:
       $this->assertTrue($variable === null)

Is same as

$this->assertNull($variable)

But using the second approach clearly indicates the issue in test failure output.

  • Similarly, using a specific assertion method can make code more readable. For example:
$this->assertEquals(
             $this->helloService->
getSomethingUseful(
$variable
, 'user1'
, []
),
null
 );

 

Using $this->assertNull instead will make it easier to see what’s being asserted.

  • Each assert method accepts an optional message argument which allows you to pass a custom error message to the output
$this->assertTrue(false, "My custom failure msg");

 

  • A useful convention is to put the expected variable in assertEquals() as the first argument and the actual as second. For example when we are expecting a string “5” from the function call:
this->assertSame(
        	"5",
        	$SomeObject->getNumber()
    		)

 

That’s all for you to get started with PHP Unit. Happy Unit Testing.

 

 

CALL

USA408 365 4638

VISIT

1301 Shoreway Road, Suite 160,

Belmont, CA 94002

Contact us

Whether you are a large enterprise looking to augment your teams with experts resources or an SME looking to scale your business or a startup looking to build something.
We are your digital growth partner.

Tel: +1 408 365 4638
Support: +1 (408) 512 1812