cult3

Getting started with PHPUnit

Mar 13, 2013

Table of contents:

  1. Install PHPUnit via Composer
  2. Setting up a test
  3. Writing the first test
  4. Watching a test fail
  5. Writing just enough code
  6. Assertions
  7. Conclusion

On Monday I introduced the concept of Test Driven Development. Test Driven Development is a programming methodology that promotes writing unit tests before you write your actual code. This means that every aspect of your code will have a explicit test to ensure that it is functioning correctly. By writing your tests from the outset, you are left with an automated testing process that can be run during Continuous Integration.

PHPUnit is the de-factor standard for Unit testing PHP. PHPUnit is essentially a framework for writing tests and the necessary tools that you will need to run tests and analyse the results.

In this post I will show you how to get up and running with PHPUnit and how it should fit into your workflow.

Install PHPUnit via Composer

The first thing we need to do is to install PHPUnit through Composer. By doing this, we can set PHPUnit as a dependency on our project which can managed easily going forward.

If you are unfamiliar with Composer, take a look at What is PHP Composer?

So firstly, create a new folder and a new composer.json file. In your Composer file, write the following:

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

Next, open Terminal and run:

$ composer install

Composer should now automatically download PHPUnit into your project and set up all the required files. If everything has worked correctly you should now have a vendor folder that contains PHPUnit amongst other things.

Setting up a test

Now that you have PHPUnit set up, we can start writing some tests.

When writing tests, you should keep them all together in the same directory. So first, move back to the root of your project and create a new directory called tests.

For this tutorial, I’m going to be creating a Car class. So within your tests directory, create a file called CarTest.php. It’s common practice to name your test classes after the real class but with “Test” appended. You don’t have to do this, but it will make things a lot easier when you come back to it or another developer has to continue your work.

In the CarTest.php file, create a new Class that extends PHPUnit.

class CarTest extends PHPUnit_Framework_TestCase
{
}

Writing the first test

Next we will write our first test. The first test I want to write is to test that the name of the car is getting set correctly when the Class is instantiated. To do that, we can write a test like this.

public function testName() {

}

First we create a new test method. You should always start your test method names with “test” and then describe your test using camel case.

Next we can create a new instance of the Car class

public function testName() {
    // Create new Car and pass in a name
    $car = new Car("Murcielago");
}

Watching a test fail

Hopefully you will have noticed that we haven’t actually created the Car class so it would be impossible to create a new instance of it. So now that we have written our test, we can run PHPUnit and watch it fail.

Open up Terminal again and run the following command:

vendor/bin/phpunit tests/CarTest.php

This simply runs PHPUnit on our CarTest.php file. You can alias the PHPUnit command so you don’t have to type out the full path name.

Once you have run that test, you should have got the following error:

PHP Fatal error: Class 'Car' not found

As you probably guessed, the test failed because there is no such thing as the Car class.

Writing just enough code

To make the test pass, we need to actually create a Car class. So back in the root of your project, create a new file called Car.php and write the following:

class Car
{
}

Next, in your CarTest.php file, add the following line to include the Car class.

include "Car.php";

Next run the same test again. You can just hit the up arrow key in Terminal to run recently run commands again.

If you have done everything right, the test should pass. Congratulations, you’ve just taken your first big step in Test Driven Development!

Let’s quickly review what we have done so far. First, we wrote the test for our required functionality. Second, we watched the test fail. Third, we wrote just enough code to make the test pass.

Hopefully if Test Driven Development seemed a bit foreign to you at the start of the this tutorial than the process that we’ve just stepped through should clear it up. Essentially, Test Driven Development is just breaking down the problem, creating a test to ensure what we are hoping to achieve will work, watching it fail and then writing the code to make it pass. In this way we can be sure that what we are writing is going to be working exactly as we expected it to do. In the future, if we ever write code that breaks this test, we will be alerted to it by running PHPUnit.

Assertions

If you flick back to your Terminal and read the output, you should notice following line:

OK (1 test, 0 assertions)

Our test passed, but we didn’t actually test to see if the name was getting set correctly.

We can now write the test to assert if the name is getting set correctly or not.

Go back to your CarTest.php file and add the following to the testName() method:

public function testName() {
    // Create new Car and pass in a name
    $car = new Car("Murcielago");
    // Get the car name
    $result = $car->name();
    // Assert that the name has been set correctly
    $this->assertEquals("Murcielago", $result);
}

Now run the test again in Terminal. You should get the following error.

PHP Fatal error: Call to undefined method Car::name()

Looks like we haven’t created the name method yet. Open up Car.php and create the name method.

public function name() {
}

Now run the test again. You should get the following error.

Failed asserting that null matches expected 'Murcielago'.
Tests: 1, Assertions: 1, Failures: 1.

Perfect! Our test failed for exactly the reason we were looking for. The name of the car is not being set. Next we can write the code to make the pass test.

First declare the name as a property of the class:

protected $name;

Next add a construct method that set’s the name when the class is instantiated.

public function __construct($name) {
    $this->name = $name;
}

Next return the name within the name method.

public function name() {
    return $this->name;
}

Next run your test again. You should get the following result:

OK (1 test, 1 assertion)

Woohoo, our test passed! So as you can see, first we wrote our test and let it fail, then we wrote just enough code to make it pass.

Conclusion

This is really just scratching the surface of Test Driven Development with PHPUnit. In the future I will write more in-depth tutorials on how you should write tests for each aspect of your application.

Hopefully for now, you should have a strong grasp of Test Driven Development, you’ve seen how it works in real life and I’ve shown you how to get started.

Now go write some tests.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.