PHP Unit Testing

PHP Unit Testing

Unit testing can reduce the number of headaches you may have with a large project. You should test each “unit” or piece of code. While it may be difficult for 100% code coverage (testing everything), it should be something you aim to do. I’ll cover assertions, methods, doc blocks, and continuous integration.

If you add your tests as you code, you’ll have assurances that anything new you write won’t affect the code you previously wrote. If it does, then one of your previous tests should fail.

Assertions

An expression which, if false, indicates an error.

To make an assertion, you’ll need to have something to assert. If you have a method that multiplies integers by five, you know if you pass in three, you’ll get fifteen. So, that could be an assertion you test. When writing your methods, you’ll know what they are returning, and it it’s good practice to test it.

Methods

At the time of writing this, there are 48 assert methods in PHPUnit. Here is a list of assert methods that you may commonly use:

  • assertContains()
  • assertEmpty()
  • assertEquals()
  • assertFalse()
  • assertFileExists()
  • assertFileIsReadable()
  • assertFileIsWritable()
  • assertGreaterThan()
  • assertGreaterThanOrEqual()
  • assertInstanceOf()
  • assertInternalType()
  • assertJsonStringEqualsJsonFile()
  • assertNull()
  • assertSame()
  • assertTrue()

The above list should be enough to get you started. The PHPUnit manual will always have an up-to-date list you will reference.

Annotations

An annotation is a neat little way to add some additional assertions to your code. If you’re familiar with documentation blocks (doc blocks), then I hope these will look familiar. They must start with “/**” and end with “*/.” The annotation begins with a “@” sign immediately follow by the assertion you wish to use. One of the ones I use a lot is the “@expectedException,” which if an exception is triggered, this will catch it and the test will pass.

Example

In this example, we are testing the add method of the Calculator class, as we should test every method of each class. Testing each unit of code is important.


<?php

class Calculator
{
	public static function add($firstNumber, $secondNumber)
	{
		return $firstNumber + $secondNumber;
	}
	// . . .
}

class CalculatorTest extends PHPUnit_Framework_TestCase
{
	public function testAdd()
	{
		$sum = Calculator::add(40, 60);
		$this->assertEquals($sum, 100);
	}
}

Since we know that 60 plus 40 equals 100, we can assert that the $sum will be equal to 100. Granted this is an elementary example, I hope it helps you understand how, why, and what a unit test is.

Tips

Your tests should not need a network connection or require on anything else other than your code. Use Mock objects when you need to “pretend” to do things. In my PHP DigitalOcean API client, I don’t want to create/delete/resize a Droplet every time I run my tests; that would cost me money.

Continous Integration

Your tests may pass on your local machine, but what if someone wants to use it running a different version of PHP? If someone pulls your code down to a new server, will it work as it should? There are a lot of reasons to incorporate continuous integration into your workflow, but I won’t try to cover them all.

I am a fan of Travis-CI as they provide free unit testing for your open source repositories. I currently test on PHP 5.6 and up, which includes the nightly build, this helps ensure my code will continue to work on later releases of PHP. You will need to add a .travis-ci.yml file to your code and can reference my Travis-CI file to get started.

If all your tests pass, then you can have your code automatically deploy to your live website or application. Hopefully, you will write enough tests to ensure it doesn’t crash.

Conclusion

Unit Testing may sound like a big leap for someone just beginning, but you will thank yourself later if you start now. You should commit frequently, test everything, and keep practicing.

More importantly, find your way of doing things, a way you’re comfortable with, that you understand. Do what makes you happy as long as you aren’t hurting others, and you will succeed.

Grasping these concepts can be difficult on your own, so if you ever have questions or need help, send me an email. Reference the PHPUnit book if you like raw documentation.