Saturday, February 2, 2008

What is Unit Testing?

Agile software development processes require a foundation built on unit testing. To successfully integrate unit testing into the development process, a framework in which test suites can be created in parallel to application code is necessary. Developers should focus on creating unit tests that exercise system functionality with pass/fail results. The granularity of tests needs to be scrutinized in that one wouldn’t create tests for trivial operations and shun creating tests that have a high degree of coupling across the system. The ideal granularity is somewhere in between; to evaluate the function and system requirement driving that unit of code. The goal in integrating unit tests into the development process is to give developers a tool that they can leverage to quickly test large sets of system functionality during development. Further, that the growing set of unit tests become the regression test suite that are run as a “smoke test” after every automated system build out of the source control management system. Having a comprehensive set of tests is the keystone that gives developers the “courage” to take on re-factoring of existing code because they can immediately know whether they’ve broken functionality and specifically what is failing as a result of their actions.

Sunday, October 28, 2007

Don't Tread on My Data

"const" Means const

Method call parameter lists are contracts, plain and simple. They are meant to be held inviolate by the implementation of the method. To break that contract is to commit programming malfeasance. Here's something you should never, ever, ever do lest you earn a place across the River Styx condemned to debug memory leaks into infinity.

void ABadBadThing( const void* pData )
{
unsigned* pDataIn = (unsigned*) pData;

...

// Now go trample all over the callers data
*pDataIn = someUnsignedValue;

return;
}

Is it apparent what has happened? Classic "bait and switch." The implementer of this function has made a contract with me, the client, that if I call this method my data is "const" which means I can assume that it will be unchanged by the call. "const void* pData" means that what pData points to is immutable, it won't be changed; what goes in, comes back out.

The heinous sin was committed by the cast operation “unsigned* pDataIn = (unsigned*) pData" which in effect strips off the "const" attribution in the parameter list by creating a mutable alias to my data. The implementation of the method is now free to go take a big poop all over my data.

There are two parties to blame here. The first is the implementer that at some point was thoughtful enough to put a "const" on the parameter, then at some point decided to coerce the pointer into a mutable type. The second is the C++ programming language which allows users to abuse type casting.

Sometimes C++ makes me feel dirty and in dire need of a shower to cleanse myself. This is another one of those times. I found this little gem in library code I inherited for a project and it cost me about a day of debugging because I assumed my data would be unchanged when it came back.

Fool me once, shame on me.