Positive and Negative Testing in C#

June 27th, 2007 by Sameer | Filed under .NET articles, Software Engineering.
In testing, there are two complementary concepts we need to understand–positive testing and negative testing.
 
For the sake of this example, positive testing refers to testing that things do what they should–for example, if you calculate the sum of two numbers, does it return the correct sum? Does sum(1, 2) return 3?
 
Negative testing refers to testing that things don’t do what they shouldn’t–for example, if you try to calculate sum("test", 4) you shouldn’t get a valid result!
 
The key to remember is positive and negative testing, together, give you comprehensive coverage of functionality–you’ve verified that the program does what it should do, and only what it should do, no more. There is no margin for ambiguity.
 
To clarify this, let’s jump to some code. Say you had a function that returns the greatest common denominator of two numbers:
public sealed class ExtendedMath
    {
        ///<summary>
        /// Find the greatest common denominator of two numbers.
        /// Note this is based on the Wikipedia pseudocode.
        /// eg. findGcd(6, 8) will return 2
        ///</summary>
        ///<param name="a">The first number</param>
        ///<param name="b">The second number</param>
        ///<returns>The GCD of a and b</returns>
        public static int FindGcd(int a, int b)
        {
            int t;

            while (b != 0)
            {
                t = b;
                b = a % b;
                a = t;
            }

            return a;
        }
    }
}
Now, to do some positive testing, you need to verify the function works. You might write the following:
            Debug.Assert(ExtendedMath.FindGcd(6, 8) == 2);
            Debug.Assert(ExtendedMath.FindGcd(3, 4) == 1);
            Debug.Assert(ExtendedMath.FindGcd(27, 27) == 27);
            Debug.Assert(ExtendedMath.FindGcd(3, 21) == 3);
(For the sake of berevity, we omitted writing actual NUnit test-cases.)
 
If you wrote those "tests", well and good–you’ve now tested that the GCD function returns what it should, given some sort of input. Note you have a few interesting cases–the second case, when the GCD is one; the third case, when the two numbers are equal; and the fourth case, when one of the numbers is the GCD.
 
In fact, by now, you’re probably feeling a little smug–only six lines of code to calculate the greatest common denominator of two numbers!
 
Now, let’s get a little fancy, and write a form that’ll take in two numbers in input-boxes (uxA and uxB) and a button (uxCalculateGcd), and show the GCD in a pop-up, like so:
 
 
And the code for the button:
 
public partial class GcdView : Form
    {
        public GcdView()
        {
            InitializeComponent();
        }

        private void uxCalculateGcd_Click(object sender, EventArgs e)
        {
            int firstNumber = int.Parse(this.uxA.Text);
            int secondNumber = int.Parse(this.uxB.Text);

            int result = ExtendedMath.FindGcd(firstNumber, secondNumber);
            MessageBox.Show(string.Format("The GCD of {0} and {1} is {2}", firstNumber, secondNumber, result));
        }
    }
If you try this with -8 and 12, we get the message "The GCD of -8 and 12 is 4", which seems correct. But what if we try this with 8 and -12? The function returns -4! Can -4 be the GREATEST common factor of 8 and -12? No, because 1 is always the common factor!
 
AHA! There, we’ve stumbled onto something–we’ve tested the function with input outside of its valid range, i.e. written a negative test!
 
To fix this, we should modify our function to return 1 if either of the numbers are negative, like so:
 public static int FindGcd(int a, int b)
        {
            if (a < 0 || b < 0)
            {
                // Not valid input
                return 0;
            }

            int t;

            while (b != 0)
            {
                t = b;
                b = a % b;
                a = t;
            }

            return a;
        }
(New code indicated in bold)
 
Now, running our function with these values gives us 0. (To be smarter about it, we could do some checking in the GUI and show an error-message if either number is negative; or we could apply some Debug.Assert statements into the beginning of the function to ensure that the input values are 0.)
 
What about if we enter 23 and "test"?   We get a FormatException, like so:
 
 
(To write this as a test case, we would have to set the text-box text, hit the run button, and catch a FormatException; if the exception wasn’t caught, then the test should fail.)
 
And that’s positive and negative testing in a nut-shell, the Sharp Developer way!

 

Other Interesting Posts

Share Your Thoughts

Valid XHTML 1.0 Transitional Valid CSS!