Tuesday, October 24, 2006

Boundary Testing Parameters

Programs (method code, procedures, etc.) must be checked for invalid parameters. This type of testing falls within the Black Box Testing category. There are many good arguments to support the notion that boundary testing is essential. The counter argument is that a developer, through the analysis of business logic, form design, and database management has already handled boundary issues at higher levels and that testing within a program would be redundant. This argument is flawed in my opinion. In an age where code reuse is stressed and when multiple developers work on the same project, boundary tests become invaluable. In addition, boundary testing will catch hidden problems in the source code, saving you and your clients time and aggravation.

So now you’re on the boundary test bandwagon; let’s consider the simplicity of the task. There are actually two elements to these tests: preparing programs for out-of-bounds values and writing test scripts that will exercise these conditions. I’ll tackle the former in this article and the latter next week.

In many cases a simple IF construct will suffice at the top of the program to verify that the parameter passed is within the expected range. It is a good practice to consider the range of known good values and work from there. Using functions such as EVL, BETWEEN, INLIST, ISNULL, and EMPTY are a good way to start. But before we go any further, it is worth mentioning that not all parameters should be treated equally. Your boundary tests will need to consider the purpose of the parameter and not just its value. For example, does the parameter control the flow of the procedure (aka a “driver”) or is it data that will be inserted into a table or used in a calculation? Boundary tests should also be clever enough to account for parameters passed by reference or value.

Processing speed should not be an issue. Many of these checks are simple enough not to bring your application to a grinding halt. If a function is to be called repeatedly in a loop, then you may consider wrapping your boundary tests in pre-processor directives. You can compile different testing and productions versions quite easily using this method.

To test parameter boundaries at the top of a program, consider some of the following techniques:


********************************************************
* using the conditional if
********************************************************
tnNumber = IIF(BETWEEN(tnNumber,nLowValue,nHighValue),;
tnNumber,nLowValue)
tcFormMode = IIF(INLIST(tcFormMode,"add","edit","readonly"),;
tcFormMode,"readonly")

*******************************************************
* using EVL() to make sure a parameter is not empty
* Note: The numeric value of 0 evaluates to empty
*******************************************************
tcPara1 = EVL(tcPara1,"Processing...")
tnPara2 = EVL(tnPara2,1)
tdPara3 = EVL(tdPara3,DATE())

*******************************************************
* using the if block
*******************************************************
IF LEN(ALLTRIM(tcLastName)) > 20
MESSAGEBOX("The last name is too long!")
ENDIF

*******************************************************
* using one parameter to test another (VFP9 example with ICASE)
* this example checks a security parameter and returns the account
* number if security is 1 (an administrator), if security is 2, a
* masked account will be returned. Otherwise, nothing is returned.
*******************************************************
tcAccount = ;
ICASE(tnSecurity=1,tcAccount,;
tnSecurity=2,CHRTRAN(cNum,lcString,"**********"),;
'')

*******************************************************
* Directories and filenames should be put through the ringer.
*******************************************************
tcFileName = DEFAULTEXT(tcFileName,"txt")
tcFileName = FORCEEXT(tcFileName,"txt")
tcFileName = IIF(FILE(tcFileName),tcFileName,GETFILE())
*
************************************************************


Next week I will explore ways of writing test scripts to pound programs into oblivion, attempting to break them every which way. It may get bloody so perhaps it is appropriate that this entry will come out next week around Halloween!

No comments: