Consider a function called openCDTray( ) which ejects a CD from the drive.
This function should be operated only when the CD tray is closed. The function also has the following constraint(for effect). Attempting to open the tray when it is already open could result in the tray falling off and reattaching the tray is a cumbersome activity! :-)
The system maintains the status of the tray in a global variable/object called gCDStatus. openCDTray( ) should check the status and then only attempt to eject; otherwise all hell would break loose. But does the function implementation take care of this? Maybe the developer thought that nobody in their right mind would do such a thing and omitted the check. It's so obvious!
A unit test-case to check the response of the function in such a scenario could simply do the following:
1. Set gCDStatus to TRAY_IS_OPEN.
2. Call the function.
3. Check the result. The function should not have succeeded.
But our developers would never skip such basic checks! But even in such cases, unit-test can catch errors that could be missed in a cursory inspection of the code.
1. Typos in the assertion-check.
if ( gCDStatus = TRAY_IS_OPEN) throw ExceptionAlreadyOpen;
or if you consider that to be improbable too
if( gCDStatus = CD_EJECTED) throw ExceptionAlreadyOpen, where CD_EJECTED is a similar-looking, but different valid value for gCDStatus
2. The openCDTray( ) function might have been modified (copy-paste!) and the programmer inadvertently does something that causes a change of the gCDStatus value.
The unit-test also helps to find out whether the assertion-check has in fact been skipped. This becomes crucial during integration and has to be guaranteed before functional testing starts.
1. The user of the function may not be aware of all the preconditions and hence may not ensure all of them before calling the function.
2. The definition of another part of the system may have changed.
In the example of openCDTray( ) , we would be saved a trip to the CD repair shop by the unit-test!