Search This Blog

2011-02-17

C# numbers and specifications

This is my kick-off post on this blog :-)
As a .NET developer I use VS, Resharper and other tools that help me to improve the process. But all these tools enfeebles us not to think about the origins - language specifications.
Let's write some tests using NUnit. So all I want to do is to multiply two various integer numbers....
[TestCase(100, 25)]
[TestCase(int.MaxValue, int.MaxValue)]
public void MultiplyNumberTest(int number1, int number2)
{
  var result1 = number1 * number2;
  var result2 = (long)number1 * number2;
 
  Assert.AreEqual(result1, result2);
}
The result1 was calculated without any conversion, but the second one was manually converted to long because a result number might be bigger than maximum value of Int32. The first test case is passed since 25 * 100 can be packed to integer but the second one fails with an error: "Expected: 1  But was:  4611686014132420609".
While calculation huge numbers the result of the first operation does not fit the integer value, so it has been truncated (Note: if checked keyword was added an overflow exception would be thrown), and VS or Resharper does not warn us about that :-).

The second example is about specifications as well.
I saw a project where logging was tested with divide by zero exception, that was a little bit strange :-). What will happen if we divide a number by zero? Exception... Yes, but only for integer division.
[Test]
public void FloatDivision()
{
  float a = 0;
  float b = 434 / a;
  
  Assert.That(float.IsInfinity(b));
}
This test is passed because floating-point division results are different.

Conclusions:
1. The language specifications should be taken into consideration!
2. We should write unit tests if it is possible, and more, cover our test code with possible scenarios. The first example demonstrates negative consequences if  the boundary values are forgotten.

2 comments: