Параметризованный тест в JUnit и Nan

197
12 августа 2017, 01:52

Здравствуйте. Подскажите, как правильно обрабатывать тесты, когда тестируемая функция выдаёт разные по типу результаты. Например, есть вот такой тестируемый класс:

public class Calculator {    
    public Double leg(int hyp, int leg){
        if (Math.abs(hyp) < Math.abs(leg))
            return Double.NaN;
        return Math.sqrt(Math.pow(hyp, 2) - Math.pow(leg, 2));
    }
}

Вот тестовый класс:

import org.junit.*;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.number.IsCloseTo.closeTo;
import static org.junit.Assert.*;
@RunWith(Parameterized.class)
public class CalculatorParametrizedTest {
    public Calculator calculator;
    private int hyp;
    private int leg;
    private double expected;
    @Parameterized.Parameters(name = "Тест {index}: гипотенуза = {0}, катет = {1}, катет = {2}")
    public static Iterable<Object[]> dataForTest() {
        return Arrays.asList(new Object[][]{
                {5, 4, 3},
                {5, -4, 3},
                {-5, 4, 3},
                {-5, -4, 3},
                {4, 5, Double.NaN},
                {3, 2, 2.24}
        });
    }
    public CalculatorParametrizedTest(int hyp, int leg, double expected){
        this.hyp = hyp;
        this.leg = leg;
        this.expected = expected;
    }
    @Before
    public void setUp(){
        calculator = new Calculator();
    }
    @After
    public void tearDown(){
        calculator = null;
    }
    @Test
    public void testLeg(){
        assertThat(calculator.leg(hyp, leg), is(closeTo(expected, 0.1)));
    }
}

Не проходит тест со значением {4, 5, Double.NaN}. Вот описание ошибки:

java.lang.AssertionError: Expected: is a numeric value within <0.1> of but: <NaN> differed by <NaN>

Я понимаю, что сравнивать NaN и NaN бессмысленно, но как правильно написать тест- не понимаю. Как правильно написать тесты для приведенной в примере функции leg?

Answer 1

assertEquals(double expected, double actual, double delta) учитывает NaN при сравнении.

Из документации:

NaNs are considered equal: assertEquals(Double.NaN, Double.NaN, *) passes

Пример:

assertEquals(expected, calculator.leg(hyp, leg), 0.1);

Дополнение по матчерам: Matchers.closeTo не учитывает NaN и я не нашел готового метода в hamcrest, который бы сравнивал подобным образом.

Можно написать условие самому, используя notANumber:

if(Double.isNan(expected)) {
     assertThat(calculator.leg(hyp, leg), is(notANumber()));
} else {
     assertThat(calculator.leg(hyp, leg), is(closeTo(expected, 0.1)));
}

, но это похоже на велосипед.

В обсуждении похожего вопроса на Github предлагают написать такой матчер:

 Matcher<Double> isCloseEnoughTo(double expected, double delta) {
      return Double.isNaN(expected) ? Matchers.notANumber() : Matchers.closeTo(expected, delta);
 }
READ ALSO
Как получить logcat удаленно?

Как получить logcat удаленно?

Скажите пожалуйста есть ли средство какое - нибудь чтобы получать логи, такие же как в LogCat

263
Очередная возня с кодировками и JSP

Очередная возня с кодировками и JSP

Всем привет! Сегодня делая сайт с помощью Java и фреймворков столкнулся с очередной непонятностьюУ меня есть jsp страничка там обычная таблица...

159
Excel-Intelij Idea-Posgresql

Excel-Intelij Idea-Posgresql

добрый день помогите отладить программуесть три класса Consumer, Parser, Connection

231