Boundary Testing — CASE: Get Median function
Last week I talked about boundary testing parameters with a promise to discuss testing methods this week. I’m going to adjust this promise a little due to the magnitude of the task. I felt it would be beneficial to review a case first.
This week, I present a simple program that I wrote several years ago that calculates the median of a range of values. I have enhanced (famous last words) the program to accept a variety of inputs that will help to demonstrate my boundary testing example next week. It has a driver parameter (tnType) and two additional parameters (teName, teColDel) that hold different data types depending on the driver.
There is no concept of overloading functions in VFP. The technique I am using for the get_median fucntion below simulates this concept. Finding the median of a cursor, array or delimeted string is not particularly hard to do, but developing a bullet-proof solution that handles each case in one shot, is.
The following program works, but has several flaws. Next week I will present an improved get_median function that addresses these flaws. I’ll expose some of them using boundary testing routines.
*-- The following creates a simple test to run get_median cString = "1,2,3,4,5" CREATE CURSOR crTemp (col1 c(1), value n(1)) INSERT INTO crTemp VALUES ("1",1) INSERT INTO crTemp VALUES ("2",2) INSERT INTO crTemp VALUES ("3",3) INSERT INTO crTemp VALUES ("4",4) DIMENSION aTestMedian[5,2] aTestMedian[1,1] = 1 aTestMedian[2,1] = 2 aTestMedian[3,1] = 3 aTestMedian[4,1] = 4 aTestMedian[5,1] = 5 ? get_median(1,cString,',') ? get_median(2,'crTemp','value') ? get_median(3,'aTestMedian',1) *-- The following is the first version of get_median FUNCTION get_median LPARAMETERS tnType, teName, teColDel *-- local declerations LOCAL lcSelCol AS String LOCAL lnItems, lnHalf, lnInc AS Integer LOCAL lnMedian AS Number *-- create the aMedian Array DO CASE CASE tnType = 1 && use a delimted string lnItems= ALINES( aMedian , STRTRAN(teName ,teColDel,CHR(13)) ) FOR lnInc = 1 TO lnItems aMedian[lnInc] = VAL(aMedian[lnInc]) NEXT CASE tnType = 2 && calculate using an alias lcSelCol = FIELD(teColDel,teName) lcSQL = "SELECT " + lcSelCol + " FROM " + teName + ; " ORDER BY " + lcSelCol + " INTO ARRAY aMedian" &lcSQL lnItems= _TALLY CASE tnType = 3 && calculate using an array lnItems= ALEN(&teName,1) DIMENSION aMedian[lnItems] FOR lnInc = 1 TO lnItems aMedian[lnInc] = &teName.[lnInc,teColDel] NEXT ENDCASE *-- find the medianASORT(aMedian) lnHalf = CEILING( lnItems / 2) IF MOD(lnHalf,2) = 0 lnMedian = ( aMedian[lnHalf] + aMedian[lnHalf+1] ) / 2 ELSE lnMedian = aMedian[lnHalf] ENDIF RETURN lnMedian ENDFUNC
I'm a Quant Technical Specialist (Data Warehousing and Business Intelligence), with expertise in business analysis, data modeling, and data integration. I have extensive experience developing vertical and integrated desktop, Internet, and BI applications spanning municipal, clinical, and financial industries.
