Test Driven Development in PHP

447

Test Driven Development (TDD) is a software development approach where tests are written first and then code passing the test is written. In other words, In TDD, we write the test first and that test drives the development of a new feature. Tests are nothing but requirement conditions that we need to test to fulfill them. The code is written usually in a short iterative cycle. TDD was first introduced by Kent Beck in 2002 and has been following by agile teams since.

TDD has three core rules:

  1. You are not allowed to write any production code if there is not a failing test to warrant it.
  2. You are not allowed to write more of a unit test than is strictly necessary to make it fail. Not compiling / running is failing.
  3. You are not allowed to write more production code than is strictly necessary to make the failing test pass.

So, what are the steps to follow while using TDD approach in programming? A general TDD coding practice has the following steps while developing a software.

  • Write a test
  • Run it and see it fail
  • Write some code
  • Run the tests and Refactor code
  • Repeat the process until completed
Note: Checking if something is indeed what we expect it to be is called asserting in TDD

There are different types of Testing: Unit Testing, Integration Testing, Functional Testing, Acceptance Testing, and so on. Among these, we will implement Unit testing for TDD approach using PHPUnit.

We will be doing unit testing in this TDD. So, what is Unit Testing? In simple words, Unit testing is a software testing method where individual units of source code are tested to make sure the code meets our requirements.

Advantages of TDD

So, we got the basic understanding of TDD. What are the advantages of this approach. Here are some the the benefits that TDD practice gives us over manual testing.

  • TDD ensures that the code works correctly now and in the future
  • TDD helps to build system with higher code quality
  • It makes developer easy to maintain and refactor
  • Easy to add features on the existing system
  • It helps to build a robust system with code flexibility
  • It helps to cut cost in the long run
  • Tests works as a additional documenttation
  • and so on

Install PHPUnit

PHPUnit is a tool that allows us to perform Unit testing. PHPUnit is a programmer-oriented testing framework for PHP. Some PHP frameworks such as Laravel comes with pre-installed PHPUnit. But, we will start from the basic i.e. we will install PHPUnit is a fresh PHP project.

We will install PHPUnit on a clean project. The current version of PHPUnit is 9.5 which requires PHP version greater than 7.3. The code coverage report feature requires the Xdebug (2.7.0 or later) and tokenizer extensions. If you want to configure XDebug on Windows with VSCode, you may read this article.

We will install PHPUnit using composer. Composer is an application-level package manager for the PHP programming language that provides a standard format for managing dependencies of PHP software and required libraries.

Let’s create a project folder, inside the project directory, create a file named composer.json and paste the following code.

The require-dev packages are packages that aren’t necessary for your project to work and shouldn’t be included in the production version of your project. This PSR describes a specification for autoloading classes from file paths.

Now, open the command line and run the following:

composer install

After running this command, it will install PHPUnit and other dependencies in our application and we can start writing out test on the go.

To make sure PHPUnit is installed, we can run the command:

vendor/bin/phpunit --version

It will display the version of PHPUnit if installed correctly.

Write First Unit Test

Before we write our first test, let’s organize our files first. Create a new file Receipt.php under under src directory. We will create a class Receipt and a method to calculate a total. First of all, I will define the namespace as defined in our composer.json. In the function total, we will calculate the sum of elements of an array and return the sum.

Now, let’s write a corresponding unit test for it. Create a folder tests inside the project directory and add a file ReceiptTest.php. We have already autoload the tests directory in composer.json file, so all the files in this directory will be autoloaded.

In ReceiptTest.php file, import the composer autoload file so that we can use PHPUnit class file. After writing some tests code, ReceiptTest.php looks like below:

One Line 4, we import the autoloader. One Line 6-7, we import two classes first one is TestCase which the test class should always extend and the Receipt class because we need to instantiate this class in our test case.

The setUp() and tearDown methods are always called before every test methods. The setUp method helps to create instances of any classes or anything else we need before running our test methods. tearDown lets us remove any of those instances to ensure our test are running in isolation.

Inside setUp method, we create an instance of Receipt class and inside tearDown method, we destroy the instantiation created earlier.

Since, total method in Receipt class accept an array and return sum, we will create a test array named $input. Then, we call the total method with recently created array as parameter. From Line 20-24, we assert that our expected result is 15 and check this value with the returned value. Lastly, we return the message we want to display on failure.

Let’s run our tests. Open up the terminal and run the following code:

vendor/bin/phpunit tests

It will run the test and display the out with additional information.

Ok, we have passed our first unit test. You can find more about the available assertions at the official docs.

TDD Approach

So, now we have rough understanding of how Unit Testing works. Now, we will write code using TDD. Out first step will be to write a failing test. We will write a test to calculate tax. We will add new method testTax and follow the process as in earlier steps. We will give input, output, and assert the test.

Now, run the test with the followng command:

vendor/bin/phpunit tests

When we run the test, the first test will pass, and the second will fail. Second test will fail because we haven’t written the method Tax. Thus, we get the Error: Call to undefined method TDD\Receipt::tax().

Let’s go to our Receipt class in source code create a new method defined in our test.

public function tax($amount, $rate) {
    return $amount * $rate;
}

After adding tax method in our code, when we run the test, the code will pass. In this way, our test method provides what changes needs to be done to make the test pass and correspondingly our code to be working.

Read More Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.