char upcase( char x ) { if ( (x > 'a') && (x < 'z') ) return x + ('A'-'a'); else return x; }Of course, you immediately spotted that it should have been:
char upcase( char x ) { if ( (x >= 'a') && (x =< 'z') ) return x + ('A'-'a'); else return x; }
Experienced programmers know that certain errors, like writing '>' rather than '>=' are so easy to make and so easy to miss on inspection of code, that they will treat the boundary cases as separate equivalence classes. This expands the equivalence classes to:
values of x |
|
If I had not seen the code and was generating test cases for this case from the specification, then I would assume that the programmer would use the order of the ASCII characters, but I wouldn't know whether he or she had chosen to write:
if ( (x<='`') || (x>='{') ) return x; else ...so I would include values on both sides of the boundary just as a precaution.
Further extension of the boundary value argument would suggest that the values: 0, -1, any other negative value, 255, 256 and a value > 256 should be added to check that extremities of the legal range are correctly processed also.
Other domains have their special values, which should be routinely included also:
While not formally required, these few extra tests - added because I know something about how the program is likely to be constructed - do no harm (and may save you if a programmer - at some later stage - decides to change the implementation, makes a mistake doing it and forgets to change the test suites also!). The important consideration here is that these extra tests have been added because we know something about typical programming errors or ways that the function could be changed. They are not just random values which could all lie in the middle of some equivalence class and represent totally useless tests!
Again boundary and special values need to be included: for instance your test set for a word processor should include