CS 211 - Note for Friday 9/16/16 To write to STANDARD ERROR fprintf ( stderr, "Error Message ... \n", value); Also note that: printf ("Message .....", value... ); is the same as: fprintf ( stdout, "Message .....", value... ); -------------------------------------- Testing a Program 1. Requires the developer to fully understand the full range of possible input scenerios. When running a program to verify it is correct, we need to give it both valid and invalid input. One approach to testing is to create "Equivelence Classes of Input" ---------------- Example: Simple Income Tax Calculator Program Requirements : Input $0 to $5000 => no taxes Input $5001 to $25000 => 5% tax Input $25000 to $50000 => 10% tax Input >$50000 => 15% tax Allow the user to enter in one value as Income and display the correct Tax Amount Print an error message if input is negative or non-numeric ------------------ The above example has (at least) 4 Equivelance Classes We should create at least one test case for each valid range of input The developers need to create Equivelance classes for invalid input. Equivalence Classes of Invalid input for the above example Negative input Non-numeric input For Equivalence classes the input values used for testing should come from the "middle" of the range of values accepted for each equivalance class. The value of 2500 is in the middle of range from 0 to 5000. --------- There is a second form of testing called "Boundary Case Testing", which verifies the boundaries between two adjacent Equivalence Classes. Boundary Cases examples: between 0-5000 range and 5001-25000 range between negative values and 0-5000 range Boundary cases normally require multiple test cases. one test case for the boundary value (or values) and additional cases for the next value just beyond the boundary value(s). For the above first boundary case, 3 or 4 values make sense: Test Value: 5000, 5001 (boundary values) 4999, 5002 (value just beyond the bounary) For the above second boundary case, 4 test cases make sense: Test values: -1, 0 (boundary values) -2, 1 (value just beyond the boundary) For each test case, we should create a input scheme (the entire set of input needed to the test case), and what is the expected output When testing, the result is whether the input scheme produced the expected output. Note this is a YES/NO question. Note that Testing is NOT Debugging. Testing is just finding if Errors exist. Debugging is the fixing of those errors. =================== struct linkedStruct { int elem; struct linkedStruct *next; }; typedef struct linkedStruct linked; // added a struct that will contain 2 pointers : a head and a tail struct queueStruct { linked* head; linked* tail; } typedef struct queueStruct queue; void add1 ( linked** hd, int val ) //add to the head of a linked* { // to access the list itself *hd } void add2 ( queue * q , int val ) //add to a queue { // to access the list itself q->head or q->tail } main () { linked* head; add1 ( & head , 5); queue q1; add2 ( &q1, 10 );