Skip navigation

Writing good unit test cases is hard and requires you to be paying a lot of attention to catch problems.

Consider for example, this operator/ (vector division) method for a Vector class (NOT STRUCT!)

( Since class Vector is a class and not a struct, vec will be passed by reference. )


  public static Vector operator /( Vector vec, double divider )
  {
    vec.x /= divider;
    vec.y /= divider;

    return vec ;
  }

Above code to be used as in:

Vector v = new Vector( 15, 5 ) ;
Vector w = v / 5 ;

Can you see the bug?

You really have to be paying very close attention to ideas that the original programmer (frequently you) might have overlooked when developing the method.

Remember, Vector is a class, not a struct!

Here’s a naive first attempt at Unit test for the operator/ method:

    [TestMethod()]
    public void op_DivisionTest()
    {
      // make a vector and divide it by a constant
      Vector vec = new Vector( 4.92, 8 ) ;
      double d = 7.7 ;
      Vector actual = vec / d ;

      // Find what it should actually be:
      Vector expected = new Vector( 4.92/d, 8/d ) ;
      
      // Assert result is what you expect
      Assert.AreEqual( expected, actual );
            
    }

Can you see the problem? Can you see how this unit test FAILS to catch the real problem with this method?

Look again at the original operator/ method at the top of this page. The problem with the method is it mutates vec, since vec is passed by REFERENCE only and not by value (the method would be FINE if class Vector were struct Vector instead!

So, here’s the better unit test that catches this problem:

    [TestMethod()]
    public void op_DivisionTest()
    {
      // Compute a result, and find expected value as well
      Vector vec = new Vector( 4.92, 8 ) ;
      double d = 7.7 ;
      Vector actual = vec / d ;

      Vector expected = new Vector( 4.92/d, 8/d ) ;
      
      // Test result is what you expect:
      Assert.AreEqual( expected, actual );

      // This is "writing good unit tests".  TEST FURTHER.
      // What else should be guaranteed by this method / what
      // is the programmer to naturally assume about how the
      // method behaves and what it does to its inputs?

      // 1.  A new object, distinct instance of an object should be produced.
      Assert.AreNotSame( vec, actual ) ;
      
      // 2.  vec should remain unchanged from its original value
      Assert.AreEqual( vec, new Vector( 4.92, 8 ) ) ;
      
    }

The corrected operator/ method

For instance, here is an operator/ division method for a Vector class (NOT STRUCT!)
  public static Vector operator /( Vector vec, double divider )
  {
    Vector result = new Vector() ;

    result.x = vec.x / divider;
    result.y = vec.y / divider;

    return result ;
  }

So its easy to write crummy simple unit tests that don’t catch everything!! Unit tests aren’t catch-all.. you have to write them cleverly!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: