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?
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.
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.
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.
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.
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 .
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With