assertEquals(Double,Double)和assertEquals(double,double,delta)之间的Junit差异

时间:2012-06-28 10:02:26

标签: java unit-testing junit

我有一个junit测试断言两个Double对象,其中包含以下内容:

Assert.assertEquals(Double expected, Double result);

这很好,然后我决定将其改为使用原始的double而不是原来的,除非你也提供了一个delta。

所以我想知道在这个assertEquals中使用Double对象或原始类型有什么区别?为什么在没有delta确定的情况下使用对象,但是不推荐使用没有delta的基元? Java是否在后台执行某些已经考虑了默认增量值的内容?

感谢。

6 个答案:

答案 0 :(得分:16)

没有assert method in JUnit签名

assertEquals(Double expected, Double result);

然而,对象有一个通用:

assertEquals(Object expected, Object result);

这会调用对象的equals方法,正如您所料,建议不要将其用于比较Double个对象。

对于双精度数,正如您所观察到的,绝对有必要使用增量进行比较,以避免浮点舍入问题(在其他一些答案中已有解释)。如果您使用带有assertEquals参数的double的3参数版本

assertEquals(double expected, double actual, double delta);

你的Double将被静默地取消装箱到double,一切都会正常工作(你的测试不会意外失败: - )。

答案 1 :(得分:5)

如果给出完全相同的结果,则很少使用双数学。例如,0.1 * 0.1 != 0.01。在比较双精度结果时,通常至少需要一些增量。

另一方面,如果你比较盒装的Double,它假设你想要完全相等。 Java没有考虑默认增量值,但Double.equals==的行为略有不同:特别是its handling of NaNs

这在测试中很有意义,因为Double.NaN != Double.NaN,但在测试中,如果您预期会返回NaNNaN,那么这是正确答案。

答案 2 :(得分:1)

更好地写下这样的东西:

assertEquals(23.0, 250.0, 0.0)  

0.0 - 它是delta。请阅读您的方法被弃用的原因。

答案 3 :(得分:0)

SOURCE. 断言两个双精度或浮点数等于正三角形。如果不是,则抛出AssertionError。如果期望值是无穷大,则忽略delta值.NaNs被认为是相等的。

答案 4 :(得分:0)

我会说比较双打,原始或对象,没有三角洲就没用了。了解流动点数如何工作是进行数值工作的关键。

对象可能正在使用.equals;除了==之外,原语没有其他选择。

仅仅因为对象版本没有使用delta,这不是一个更好的主意。

答案 5 :(得分:0)

我正在回答有关 JUnit 5 的更新。无论版本如何,assertEquals(Double expected, Double actual) 都会被路由到 assertEquals(Object expected, Object actual),因为正如其他人已经解释的那样,Double 是一个隐式的原始包装器扩展 Object

但是 assertEquals(double expected, double actual)(带有两个原语而不是两个原语包装器)在 JUnit 4 上下文中调用了一个不推荐使用的过程。我不知道它是否已经在 J​​Unit 3 中被弃用。但你猜怎么着:它在 JUnit 5 中没有被弃用。

double 这样的浮点类型本质上是不精确的。假设 expected = 0.3actual 是如何计算的?如果它是 3.0 / 10,结果可能是准确的。但如果它是臭名昭著的 0.1 + 0.2,它将减去 0.00000000000000004(如果减去 0.3,它会以某种方式变成 5.551115123125783 × 10−17)。

一般来说,浮点乘除法比浮点加减法更可靠。

以下示例来自带有 org.junit.jupiter.api.Assertions.* 静态导入的测试类。

    @Test
    void testDeltaExample() {
        double expected = 0.3;
        double actual = 0.1 + 0.2;
        assertEquals(expected, actual);
    }

结果:

<块引用>

org.opentest4j.AssertionFailedError: expected: <0.3> but was: <0.30000000000000004> 在 org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55) 在 org.junit.jupiter.api.AssertionUtils.failNotEqual(AssertionUtils.java:62) 在 org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:70) 在 org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:65) 在 org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:868) ...

你是否在意它是否有这么小的偏差?如果不这样做,那么您将需要 0.00000000000000001 之类的增量。

如果您愿意,您仍然可以使用 JUnit 5 中的“老式”JUnit(但您不应该出于任何原因想要迁移现有测试套件,或者看到它可以完成)。

    @Test
    void testDeltaExample() {
        double expected = 0.3;
        double actual = 0.1 + 0.2;
        org.junit.Assert.assertEquals(expected, actual);
    }

(您的 IDE 应该在右大括号之前的行中显示一个删除线)。即使 expectedactual 具有完全相同的位模式(在本例中它们不会),此测试也会失败。

<块引用>

java.lang.AssertionError: 使用 assertEquals(expected, actual, delta) 来 比较浮点数 org.junit.Assert.fail(Assert.java:88) 在 org.junit.Assert.assertEquals(Assert.java:667) 在 org.junit.Assert.assertEquals(Assert.java:656) ...

许多非常聪明的 Java 程序员学习了 SQL 连接等复杂的东西,他们根本不在乎学习浮点数,所以他们只使用了 0.0 的增量。

因此,JUnit 开发人员似乎认为教育人们了解浮点数的弱点不是他们的工作。因此,org.junit.jupiter.api.Assertions.assertEquals(double expected, double actual) 在技术上是新的,并且根本没有被弃用。

绝对清楚,在 JUnit 5 中仍然可以使用浮点数与 delta 进行比较。从 Scala 的角度来看,您可以将其视为 assertEquals(expected: Double, actual: Double, delta: Double = 0.0)