Ich antworte auf das Update bezüglich JUnit 5. Unabhängig von der Version wird assertEquals(Double expected, Double actual)
auf assertEquals(Object expected, Object actual)
umgeleitet, weil, wie andere bereits erklärt haben, Double
ein primitiver Wrapper ist, der implizit Object
erweitert.
Aber assertEquals(double expected, double actual)
(mit zwei Primitiven anstelle von zwei primitiven Wrappern) ruft in einem JUnit 4-Kontext ein veraltetes Verfahren auf. Ich weiß nicht, ob es bereits in JUnit 3 veraltet war. Aber raten Sie mal: In JUnit 5 ist es nicht veraltet.
Gleitkommatypen wie double
sind grundsätzlich ungenau. Angenommen, expected = 0.3
. Wie wird actual
berechnet? Wenn es 3.0 / 10
ist, könnte das Ergebnis genau sein. Aber wenn es das berüchtigte 0.1 + 0.2
ist, wird es um 0,00000000000000004 abweichen (was irgendwie zu 5.551115123125783 × 1017 wird, wenn Sie 0.3 abziehen).
Allgemein gesprochen sind Gleitkomma-Multiplikation und -Division zuverlässiger als Gleitkomma-Addition und -Subtraktion.
Das folgende Beispiel stammt aus einer Testklasse mit einem org.junit.jupiter.api.Assertions.*
statischen Import.
@Test
void testDeltaBeispiel() {
double expected = 0.3;
double actual = 0.1 + 0.2;
assertEquals(expected, actual);
}
Ergebnis:
org.opentest4j.AssertionFailedError: erwartet: <0.3> aber war: <0.30000000000000004> at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55) at org.junit.jupiter.api.AssertionUtils.failNotEqual(AssertionUtils.java:62) bei org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:70) bei org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:65) bei org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:868) ...
Stört es Sie, wenn es um einen winzigen Betrag abweicht? Wenn nicht, dann möchten Sie einen Delta von 0.0000000000000001.
Sie können immer noch das "Vintage" JUnit aus JUnit 5 verwenden, wenn Sie möchten (aber Sie sollten es aus keinem anderen Grund wollen, als dass Sie bereits vorhandene Test-Suiten migrieren oder sehen wollen, dass es möglich ist).
@Test
void testDeltaBeispiel() {
double expected = 0.3;
double actual = 0.1 + 0.2;
org.junit.Assert.assertEquals(expected, actual);
}
(Ihr IDE sollte eine Durchstreichung in der Zeile vor der schließenden geschweiften Klammer anzeigen). Dieser Test wird fehlschlagen, auch wenn expected
und actual
das genau gleiche Bitmuster haben (was sie in diesem Beispiel nicht haben).
java.lang.AssertionError: Verwenden Sie assertEquals(expected, actual, delta) um Gleitkommazahlen zu vergleichen bei org.junit.Assert.fail(Assert.java:88) bei org.junit.Assert.assertEquals(Assert.java:667) bei org.junit.Assert.assertEquals(Assert.java:656) ...
Viele ziemlich intelligente Java-Programmierer, die so komplizierte Dinge wie SQL-Joins gelernt haben, haben sich einfach nicht darum gekümmert, sich mit Gleitkommazahlen zu beschäftigen, und haben einfach einen Delta von 0.0 verwendet.
Und so scheint es, als hätten die JUnit-Entwickler beschlossen, es sei nicht ihre Aufgabe, die Leute über die Tücken von Gleitkommazahlen aufzuklären. Daher ist org.junit.jupiter.api.Assertions.assertEquals(double expected, double actual)
technisch neu und überhaupt nicht veraltet.
Um es ganz klar zu sagen, der Vergleich von Gleitkommazahlen mit einem Delta ist immer noch in JUnit 5 verfügbar. Aus Sicht von Scala können Sie es als assertEquals(expected: Double, actual: Double, delta: Double = 0.0)
betrachten.