Write tests, you might learn something

Writing unit tests for your code is widely regarded as a best practice. There are many excuses for not writing tests: time, cost, and the fun factor. Excuses aside, there are some Good Reasons to write tests for your code. I just discovered one today.

Write tests, you might learn something…faster

I’m working on an API integration that requires a bit of AES-256 encryption. Getting that worked out in PHP took some surprising turns, so just to be sure that I was getting all the details right (such as initialization vector size) I decided to write a unit test for my mcrypt wrapper library.

Since this library had worked well in other projects, imagine my surprise when the first AES-256 encrypt-decrypt test failed:

$ phpunit *
PHPUnit 3.7.8 by Sebastian Bergmann.


Time: 0 seconds, Memory: 2.50Mb

There was 1 failure:

1) EncryptionAes256Test::testEncryptDecrypt with data set #0 ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz')
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
+Binary String: 0x4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656668696a6b6c6d6e6f707172737475767778797a00000000000000000000000000


Tests: 4, Assertions: 7, Failures: 1.

Echoing out the decrypted string proved just as bizarre:

string(51) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz"
string(64) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz"

It seems that mcrypt pads the string with enough null characters (\0) to match the block size, and unlike strings in C, PHP strings do not necessarily end with the first null character.

The fix was obvious:

$decrypted = rtrim($decrypted, "\0");

Guess what? By investing time in a simple unit test, I unexpectedly learned something new about PHP, AND saved myself quite a bit of time debugging an API call that would not have worked.

I’d say it was worth it.

Written on April 5, 2013