Unit testing, that pain in devs’ necks

Unit testing, that pain in devs' necks

At the end of this article, there is a little guide of how to append PHPUnit to your project when it doesn’t come by default (for instance, when you don’t work with a framework), feel free to skip the story part and go there now if you need the information!

Let’s face it, most programmers hate – or at least dislike – doing unit testing, and when other seniors remind you about it as a clear example of dependency injection you probably hate it more.

It’s not a matter of when you do it: before or after implementation, during codification, in your dreams at night. Most of us, as programmers, want to deliver tangible results as soon as we can, probably because the team leader is in a hurry, the client is in a hurry or the whole project depends on your little piece of code. It’s a satisfaction to see the beautiful interfaces, the nice reports… whatever, the thing is, at the end, nobody cares about that collection of files you stored under the “test” folder.

angry user

But it’s this folder the one that will provide strength and support to all the pretty things you built for that client or for yourself. You wish those reports don’t stop working all of a sudden! Or you will have an angry client telling you that his commissions are generating an extra zero at the end of the month, and not at the left of the amounts!

 

 

 

 

 

 

 

…It’s when that sort of things happen when we recognize the good things about testing (testing of any kind). When we start doing it and we see that it really pays off because there were hidden bugs that would have surfaced under the category “on fire”.

fire fighting

To provide a brief example, some days ago we published at our TowerHouseStudio’s GitHub account a standalone library called Healthmeasures.

The code had been tested the old-fashioned way: there was another .php that was using the methods of the library trying to execute every line of code (it also helped me write the README.md). After I finished the library I executed all my “testing methods” and I felt satisfied.

The purpose of the library is to store health measures, its values by owner and to recovery the data under the form of graphs, reports or descriptive stat’s values.

Nothing strange, nothing new. Some of the metrics of my pet project were:

  • The use of 4 external libraries.
  • Around 1150 lines of PHP code of my own.
  • A 3-class library.

To protect my pride and not to publish “untested” code on GitHub I decided to include unit testing corresponding to my 3 nice classes. The big surprise came when I realized that everything started to fall apart when I changed persistence between MySQL and SQLite. In fact, by doing unit testing I had to change around 70% of the code.

After I saw all of that I was overwhelmed by emotion and my programming enthusiasm increased: I wanted to get rid of those bugs as soon as I could.

At the end, everything started to work, in MySQL and SQLite. The results were exact. I could be sure that I had finished my library!

Apendix – how to include PHPUnit super fast in your project when it doesn’t come by default.

  1. Include phpunit.phar in the root of your project, you can download it from here https://phar.phpunit.de/phpunit.phar
  2. Create a file phpunit.xml in your root indicating:
  • If you need to execute a Bootstrap code before executing the tests, in general, this always involves indicating where is your PHP autoloader (the one generated by composer)
  • The relative path of your tests folder to that XML file you’re writing. As my tests folder is in the root and inside it I have a subfolder “Measurement”, then the correct path is “./test/Measurement”. You can include as many directories as you want.

Example:

1
2
3
<!--?xml version="1.0" encoding="UTF-8"?-->

./test/Measurement/

Your tests format could be the following one:

1
2
3
4
5
6
7
8
9
10
11
12
<!--?php </p> <p>use Healthmeasures\Measurement\Measure;</p> <p>class MeasureTest extends \PHPUnit_Framework_TestCase<br ?--> {

protected function getDefaultMeasure()
{
...
}

public function testStoreSingleObjectDb()
{
...
}
}

The framework will only execute the public methods starting by the work “test”. In the example above, “getDefaultMeasure” is not a test.

Finally, to execute them, open a command line, go to the root of your project and print

1
php phpunit.phar --verbose -c phpunit.xml

And now enjoy the messages, the fixed bugs and a little personal satisfaction.

Share

Recommended Posts

Leave a Reply

Your email address will not be published.