How to compare two lists of double in JUnit

Viewed 3802

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.

7 Answers

If you are willing to change from Hamcrest to AssertJ assertions, here is a solution in java 8.

import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import org.junit.Test;
// import java.util.function.Function;

public class DoubleComparatorTest {

  // private static final Double DELTA = 1E-4;
  // private static final Function<Double, Comparator<Double>> DOUBLE_COMPARATOR_WITH_DELTA =
  // (delta) -> (o1, o2) -> (o1 - o2 < delta) ? 0 : o1.compareTo(o2);

  private Comparator<Double> COMPARATOR = (o1, o2) -> (o1 - o2 < 0.0001) ? 0 : o1.compareTo(o2);

  @Test
  public void testScaleCalculationMaxFirstPositive() {
    List<Double> expected = Arrays.asList(1.1D, 2.2D, 3.3D);
    List<Double> actual = Arrays.asList(1.10001D, 2.2D, 3.30001D);

    assertThat(actual)
        // .usingElementComparator(DOUBLE_COMPARATOR_WITH_DELTA.apply(DELTA))
        .usingElementComparator(COMPARATOR)
        .isEqualTo(expected);
  }
}
Related