In a JUnit 4 test, I have a method getValues()
that returns a List<Double>
object that I want to compare with a reference list. Up to now, the best solution I've found was to use org.hamcrest.collection.IsArray.hasItems
and org.hamcrest.Matchers.closeTo
like this:
assertThat(getValues(), hasItems(closeTo(0.2, EPSILON), closeTo(0.3, EPSILON)));
This goes well for a test that returns only few values. But if a test returns more values, this is definitely not the best approach.
I also tried the following code. The downcast to Matcher
before hasItems
is required for the code to compile:
List<Matcher<Double>> doubleMatcherList = new ArrayList<Matcher<Double>>();
doubleMatcherList.add(closeTo(0.2, EPSILON));
doubleMatcherList.add(closeTo(0.3, EPSILON));
assertThat(getValues(), (Matcher) hasItems(doubleMatcherList));
The comparison failed and I don't understand why :
java.lang.AssertionError: Expected: (a collection containing <[a numeric value within <1.0E-6> of <0.2>, a numeric value within <1.0E-6> of <0.3>]>) got: <[0.2, 0.30000000000000004]>
Is there a better way to compare two large lists of doubles? The difficulty here is that a numerical tolerance is required to validate if the result of getValues()
is equal to my reference list. This kind of comparison seems very easy for any lists of objects, but not with lists of Double
.
I think the right solution here would be a Custom Matcher. Basically something like IsIterableContainingInOrder that only works on Doubles and supports an error margin.
If you are willing to convert from List<Double>
to double[]
, assertArrayEquals allows specifying a tolerance for error:
assertArrayEquals(new double[] {1, 2}, new double[] {1.01, 2.09}, 1E-1);
In Java 8, the conversion from list to array is relatively clean (see related question). For example:
double[] toArray(List<Double> list) {
return list.stream().mapToDouble(Number::doubleValue).toArray();
}
And the assert statement could then be as follows:
assertArrayEquals(toArray(refList), toArray(getValues()), 1E-9);
p.s.
toArray
can be made to work with any Number
type by just changing the signature to double[] toArray(List<? extends Number> list)
.
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