简体   繁体   中英

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?

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.

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM