Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing class with doubles

I have a class that contains (one or more...) doubles. For example:

public class TestFloatClass{
 public double Double1{get;set;}
 public double Double2{get;set;}

 public void SetDoubleByCalculation(double value){
  Double1 = //Some calculations here;
  Double2 = //Some calculations here;
 } 
}

I want to test the SetDoubleByCalculation(double value) method, so I start writing unit tests.

TestFloatClass expected = new TestFloatClass();
expected.Double1 = 100.10;
expected.Double2 = 200.24554;

TestFloatClass actual = new TestFloatClass();
actual.SetDoubleByCalculation(Math.PI); //Just using something random here.

In this case, expected.Double1 and actual.Double1 are approximately the same. But not exactly due to floating point accuracy.

However, I'm not sure how to unit test this correctly. These are the things I have tried so far.

Including a certain delta in the equals operator

My first intuition said, well, just include the logic in the equals operator like so:

public override bool Equals(object obj){
  return Math.Abs(this.Double1 - obj.Double1) <= 0.00001 &&
              Math.Abs(this.Double1 - obj.Double1)  <= 0.00001; 
}

But as said in this Hashcode implementation double precision topic, it's just practice to do so.

Just using the Assert override

I can go on by testing it as follows:

Assert.Equals(expected.Double1, actual.Double1, 0.0000001); //Or just some precision
Assert.Equals(expected.Double2, acutal.Double2, 0.0000001);

But then again, then I have to do this for EVERY property in this class. If the TestFloatClass also had two properties VeryComplicatedClass vcc & int integer then I'd have to add those too.

Assert.Equals(expected.Double1, actual.Double1, 0.0000001); //Or just some precision
Assert.Equals(expected.Double2, actual.Double2, 0.0000001);
Assert.Equals(expected.vcc, actual.vcc);
Assert.Equals(expected.integer, actual.integer);

And it would keep growing if the class gets bigger...

So my question

What is the best way to test this class?

like image 222
Timo Willemsen Avatar asked Apr 21 '11 09:04

Timo Willemsen


People also ask

What is test doubles in unit testing?

In automated unit testing, it may be necessary to use objects or procedures that look and behave like their release-intended counterparts, but are actually simplified versions that reduce the complexity and facilitate testing. A test double is a generic (meta) term used for these objects or procedures.

How do test doubles help testing?

Test doubles help you isolate the code under test so that you can test all facets of its behavior. In this example we've replaced three of the four collaborators with test doubles, deciding to scope the test to the behavior and collaboration of the code under test and one particular collaborator.

In which case a test double is required?

A good use case for test doubles is when a system or process -- while itself not error-prone -- adds a lot of time and effort to a test. Test doubles enable the developer or QA professional to focus on the new code and not the integrations. There are five main types of test doubles: test stubs.

What is stub and mock?

Stub: a dummy piece of code that lets the test run, but you don't care what happens to it. Substitutes for real working code. Mock: a dummy piece of code that you verify is called correctly as part of the test. Substitutes for real working code.


2 Answers

Note that my response to your other question mainly criticized the use of a thusly modified Equals() together with GetHashCode() for use in a Hashtable - that just won't work, which is a good example why it's problematic to override Equals() in a way that breaks its contract. If you only use it for direct comparisons in tests, that would be OK. But it might be a better idea to have a separate comparison method (perhaps called FuzzyEquals()) for use in tests to avoid confusion.

Additionally, comparing with a fixed epsilon is problematic if your values can be very small or very large - read The Floating-Point Guide for details .

like image 44
Michael Borgwardt Avatar answered Oct 10 '22 01:10

Michael Borgwardt


You should split the tests:

Assert.Equals(expected.Double2, acutal.Double2, 0.0000001);
Assert.Equals(expected.vcc, actual.vcc);

Make (separate) unit Tests for the Double2 and vcc properties on the class of actual/expected.

like image 76
Henk Holterman Avatar answered Oct 10 '22 02:10

Henk Holterman