in

Platinum Bay

Peace, Love, and...

This Blog

Syndication


.NETicated

Pop Quiz: .NET Integers, Unit Testing, and Boundary Checking

I ask this question in a bunch of my talks, mostly because most folks aren’t aware of this. What is the bug in the following method?

public int Add(int num1, int num2)
{
    return num1 + num2;
}

Do you see it? In a simple unit test, the method appears to work as expected:

[TestMethod()]
public void AddTest()
{
    MathHelper target = new MathHelper();
    int num1 = 16;
    int num2 = 16;
    int expected = 32;
    int actual = target.Add(num1, num2);
    Assert.AreEqual(expected, actual); // PASS
}

However, what if we pass in a different set of parameters, say int.MaxValue?

[TestMethod()]
public void AddMaxTest()
{
    MathHelper target = new MathHelper();
    int num1 = int.MaxValue;
    int num2 = int.MaxValue;
    int result = target.Add(num1, num2);

    Assert.Fail("Expected an overflow exception. Received: " + result);
}

Any guesses on the outcome of this test? In actuality, no exception is thrown. The test fails with the output: “Assert.Fail failed. Expected an overflow exception. Received: -2”. The output from the fail assert is “-2”. What!? Is it a bug in the .NET framework? What’s going on?

The answer lies in that I am passing in a signed int. In a signed int, the top bit is flag bit indicating positive or negative, leaving the other 31 bits to indicate the numeric value. When doing binary math that overflows the 31 bits, the 32nd bit is switched as though it is unsigned. In this case a positive becomes a negative and the result becomes –2. Let’s hope the system isn’t trying to deposit $100 into an account with $2,147,483,647.

But what does this mean to the original method? How do we handle this scenario? The point of this experiment isn’t to demonstrate a potential issue with the .NET framework. Rather, I’d like you to take notice of the first unit test. The test does evaluate the method for proper functioning, 100% code coverage would be achieved on the Add method, and yet the issue at hand is not found. And to this I would like to make an important point:

Code Coverage is a misleading metric.

In order to properly test your code, it is important to not only make sure you test as much as possible, but to ensure you also perform boundary checking. If the max values weren’t tested, it might not have been found that the code could erase $2,147,483,749 from some pour soul’s bank account. Well, he’d be poor after the fact. Are here is my second point:

Boundary check everything.

To help solve this problem, there is a neat tool from Microsoft Research called Pex. From the Pex website:

Right from the Visual Studio code editor, Pex finds interesting input-output values of your methods, which you can save as a small test suite with high code coverage. Pex performs a systematic analysis, hunting for boundary conditions, exceptions and assertion failures, which you can debug right away. Pex enables Parameterized Unit Testing, an extension of Unit Testing that reduces test maintenance costs.

What I would really love to see someday is a combination of existing code coverage in Visual Studio Team System with parameter boundary checking in Pex to give a truer sense of test coverage. Maybe for Dev11?

Published Aug 26 2009, 08:10 PM by Steve
Filed under: , , ,

Comments

August 27, 2009 5:25 AM

Pingback from  Dew Drop – August 27, 2009 | Alvin Ashcraft's Morning Dew

 

October 6, 2010 4:03 PM

Thanks for the post, Steve!

See the paper below on enhancing Pex to deal with boundary value generation resulted from collaboration between North Carolina State University (sites.google.com/.../asergrp) and the Microsoft Research Pex group:

people.engr.ncsu.edu/.../icsm10-coverage.pdf

Rahul Pandita, Tao Xie, Nikolai Tillmann, and Jonathan de Halleux. Guided Test Generation for Coverage Criteria.

In Proceedings of the 26th IEEE International Conference on Software Maintenance (ICSM 2010), Timișoara, Romania, September 2010.

 

Leave a Comment

(required )  
(optional )
(required )  
Add

About Steve

Steve Andrews is an independent consultant, INETA speaker, and Microsoft MVP for Visual Studio ALM. He has been working in technology for over ten years focusing on custom application development and Application Lifecycle Management. Steve is also Microsoft and IBM certified and a community fanatic having led sessions at nearly 100 events across North America. When he's not developing software solutions or engaging with the community about software technology, Steve is a closet singer and songwriter and plays the guitar and keys. Occasionally, Steve even gets to sleep. Occasionally.
Powered by Community Server (Commercial Edition), by Telligent Systems
© Platinum Bay | Some Rights Reserved Creative Commons License

Disclaimer: The information in this weblog is provided "AS IS" with no warranties, and confers no rights. This weblog does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion. Feel free to challenge me, disagree with me, or tell me I'm completely nuts in the comments section of each blog entry, but I reserve the right to delete any comment for any reason whatsoever (abusive, profane, rude, or annonymous comments) - so keep it polite, please.