Book Image

Instant Hands-on Testing with PHPUnit How-to

By : Michael Lively
Book Image

Instant Hands-on Testing with PHPUnit How-to

By: Michael Lively

Overview of this book

No developer wants to accept the inherent difficulty of writing software as an excuse for not finding the bugs in our code before anyone else does. PHPUnit is a framework that was created to allow developers to solve that very problem. It provides a feature-rich environment with most of the tools necessary to provide adequate tests for any project. "Instant Hands-on Testing with PHPUnit How-to" provides a thorough overview of the functionality provided by the PHPUnit framework. It shows how the plethora of features in the framework can be used to write tests for real world projects to ensure they function and will continue to function in the ways that you expect. This book will show how you can set up the scaffolding necessary to run unit tests in your project with PHPUnit. It will walk you through the process of how to write a basic test and how to maintain your project's test suite. You will learn how to use some of the more advanced features of PHPUnit and then see how you can use mock objects to isolate the code you are testing. We will then discover how to create tests that verify your interaction with databases and even see how you can use PHPUnit to understand which code you are actually testing. At the end of the book you will have all of the basic understanding necessary to begin adding tests to your project. This book provides a great foundation for becoming a expert at writing unit tests.
Table of Contents (7 chapters)

Writing your first test (Simple)


One of the primary goals of PHPUnit is to make it easy to write tests. The easier it is to write tests, the more likely it is that tests will be written. In this recipe, we will discuss the basic parts of a test and how to implement each of those parts in PHPUnit.

Getting ready...

Each test in our system will consist of four parts: the fixture, the test, the verification, and the tear down. The fixture sets up the unit that you are testing to have the necessary state for the rest of the test. The test then exercises the system, typically by calling a single method. When verifying the test you are just checking to see if the results of our method are what you expected them to be. The tear down step is actually very rarely needed in PHP as memory management is handled for you. Occasionally, you may need to close files, delete data, or manage other external resources. The tear down part of a test is the appropriate place to do this work.

How to do it...

We will begin by testing the Card class unit.

  1. The following code defines that class and should be put in Card.php:

    <?php
    class Card
    {
      private $number;
      private $suit;
      public function __construct($number, $suit)
      {
        $this->number = $number;
        $this->suit = $suit;
      }
      public function getNumber()
      {
        return $this->number;
      }
      public function getSuit()
      {
        return $this->suit;
      }
      public function isInMatchingSet(Card $card)
      {
        return ($this->getNumber() == $card->getNumber());
      }
    }
  2. The following code defines a test for this unit and should be put in CardTest.php:

    <?php
    require 'Card.php';
    class CardTest extends PHPUnit_Framework_TestCase
    {
      public function testGetNumber()
      {
        $card = new Card('4', 'spades');
        $actualNumber = $card->getNumber();
        $this->assertEquals(4, $actualNumber, 'Number should be <4>');
      }
      public function testGetSuit()
      {
        $card = new Card('4', 'spades');
        $actualSuit = $card->getSuit();
        $this->assertEquals('spades', $actualSuit, 'Suit should be <spades>');
      }
      public function testIsInMatchingSet()
      {
        $card = new Card('4', 'spades');
        $matchingCard = new Card('4', 'hearts');
        $this->assertTrue($card->isInMatchingSet($matchingCard),
            '<4 of Spades> should match <4 of Hearts>');
      }
      public function testIsNotInMatchingSet()
      {
        $card = new Card('4', 'spades');
        $matchingCard = new Card('5', 'hearts');
        $this->assertFalse($card->isInMatchingSet($matchingCard),
            '<4 of Spades> should not match <5 of Hearts>');
      }
    }

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

How it works...

The CardTest class extends the PHPUnit_Framework_TestCase class to create our first unit test. The PHPUnit_Framework_TestCase class is what makes this a test. It takes care of all of the low-level tasks of testing for us so that we can just focus on writing the tests in an easy and concise manner.

In each of our tests you can see that we first create our fixture: one or more instances of our Card classes. Next, we call the method that we are testing. Finally, we utilize PHPUnit's assert methods to verify the results of the tested methods.

We always pass a message as the final argument to our assert functions. This will be displayed by PHPUnit should any of our tests fail due to these assertions. It can be very important as your test suite gets larger and as time passes to have a good description of our failures so that we clearly understand the expected behavior and what broke. Not only will this provide us a reminder of how the test works, it could also be invaluable to anyone else that works on our code in the future.

The other important thing to note is the require "Card.php" line. Your test will already have access to any PHPUnit framework classes and functions; however, you must include the code you are testing yourself. If this line is not present, when the test is run you will get an error because PHPUnit doesn't know about the Card class. In a later recipe we will see a much easier way to include the code.

There's more...

Even though these are all simple tests, we are beginning to see some of the simplicity of PHPUnit. One of the most important things that we need to know to effectively use PHPUnit is the basic assert methods it supplies. The ability to perform basic value checking is available, but there are also more complicated assertions possible on arrays, objects, and even XML. Have a look at http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.assertions to see all of the assertion methods you have access to.

Class names

It is a common practice in PHPUnit to name your test case class after the class it is responsible for testing. We are using that method here. The CardTest class is testing the Card class. Naming your test case classes in this fashion makes your tests easier to find and also makes it easier to understand what class a test case is responsible for covering.