简体   繁体   English

对REST的困惑确保浮点比较

[英]Confusion over REST Assured floating-point comparisons

The REST Assured usage documentation has examples like this: REST Assured 使用文档包含以下示例:

get("/lotto").then().body("lotto.lottoId", equalTo(5));

OK, so they are using a Hamcrest matcher to compare to the int value 5 . 好的,所以他们使用Hamcrest匹配器来比较int值5

But they have a section saying that the REST Assured JSON parser by default uses float and not double , so instead of comparing to 12.12 I should compare to 12.12f : 但他们有一节说默认使用REST Assured JSON解析器使用float而不是double ,所以不应该比较12.12我应该比较12.12f

get("/price").then().body("price", is(12.12f));

Wait, so how did 5 work above, which is an int and not a double ? 等等,所以上面有5工作,这是一个int而不是double Does the JSON parser use different primitives for integer and non-integer values? JSON解析器是否对整数和非整数值使用不同的基元?

But it gets more confusing. 但它变得更加混乱。 Well-versed programmers know that you shouldn't be comparing floating point values directly anyway (because of the intricacies of how floating-point values are stored, etc.). 精通程序员知道你不应该直接比较浮点值(因为存储浮点值的方法很复杂等)。 Instead you should use Matchers.closeTo(double operand, double error) which provides a margin of error. 相反,你应该使用Matchers.closeTo(double operand, double error) ,它提供了一个误差范围。 This is the correct way to do it. 这是正确的方法。 But wait --- even if I pass in 12.12f to Matchers.closeTo(double operand, double error), isn't it still going to convert it to a double ? 但是等等---即使我将12.12f传递给12.12f (双操作数,双错误),是不是仍然要将它转换为double Will this work with REST Assured? 这可以与REST保证一起使用吗?

I'm not 100% sure I'm correct here, but this post became too long for a comment... 我不是百分百肯定我在这里是对的,但是这个帖子对于评论来说太长了...

From reading the docs for Hamcrest and REST Assured it seems like equalTo only returns true in the cases that Object.equals returns true: 通过阅读HamcrestREST Assured的文档,看起来equalTo只在Object.equals返回true的情况下返回true:

[equalTo] Creates a matcher that matches when the examined object is logically equal to the specified operand, as determined by calling the Object.equals(java.lang.Object) method on the examined object. [equalTo]创建一个匹配器,匹配当被检查对象在逻辑上等于指定的操作数时,通过在被检查对象上调用Object.equals(java.lang.Object)方法来确定。

Thus since REST Assured represents floating point values as floats, and Double.equals can only return true if that other object is a Double , it is necessary to use a float and not a double (as the input will get boxed into an object). 因此,由于REST Assured将浮点值表示为浮点数,而Double.equals只能返回true如果其他对象是Double ,则必须使用float而不是double (因为输入将被装入对象)。

Also, the section of floats in the REST Assured docs seems to indicate it only applies to floating point values: 此外,REST Assured文档中的浮动部分似乎表明它仅适用于浮点值:

Floating point numbers must be compared with a Java "float" primitive. 必须将浮点数与Java“float”原语进行比较。

I presume that means that integers are represented properly as Integers. 我认为这意味着整数被正确地表示为整数。 (Other examples in the docs also seems to suggest this) (文档中的其他示例似乎也暗示了这一点)

If you chose to use Matchers.closeTo instead of equalTo or is (which itself calls equalTo ), then it shouldn't matter if you use a double or a float . 如果您选择使用Matchers.closeTo而不是equalTo或者is (这本身调用equalTo ),那么它不应该,如果你使用的事doublefloat

You can compare a lot of things with equalTo of hamcrest.Matchers, it's used also to assert in test: 你可以用很多东西比较hamcrest.Matchers,它也用于测试中的断言:

assertThat(longValue, equalTo(10L));
assertThat(cadena, equalTo("Esta es una cadena")); 

There is a comparison to Long and String, and of course, you have the closeTo to compare things such as doubles or bigdecimal, take a look here and there 有一个与Long和String的比较,当然,你有closeTo比较双打或bigdecimal等东西,看看这里那里

So indeed, is normal the surprise, but you can also choose to compare or do equals when is convenient 所以,确实是正常的惊喜,但你也可以在方便的时候选择比较或做等于

Looks like you are mixing two things together. 看起来你把两件事混在一起。

Does the JSON parser use different primitives for integer and non-integer values? JSON解析器是否对整数和非整数值使用不同的基元?

Value comparison is done by given matcher object. 值比较由给定的匹配器对象完成。 The given matcher does not have any influence on the Json Parser in anyway. 无论如何,给定的匹配器对Json Parser没有任何影响。 Irrespective of what value you have given to matcher ( 5 in first example) and what value would return by the given jsonpath, The equals matcher( org.hamcrest.core.IsEqual ) compare both valu by invoking Objects.equals() method. 无论您给匹配器(第一个示例中为5 )赋予什么值以及给定的jsonpath返回什么值,等于匹配器( org.hamcrest.core.IsEqual )通过调用Objects.equals()方法来比较两个值。 Also Json parser works with value objects and not with primitives. Json解析器也可以使用值对象而不使用基元。

so how did 5 work above, which is an int and not a double? 那么5如何在上面工作,这是一个int而不是一个双?

Assuming JsonPath lotto.lottoId would return int value, thus body("lotto.lottoId", equalTo(5)); 假设JsonPath lotto.lottoId将返回int值,因此body("lotto.lottoId", equalTo(5)); will be true (obviously json value has to be 5 ) 将是真的(显然json值必须是5

12.2' and 12.2f' are treated as same values in your example. 在您的示例中, 12.2' and 12.2f'被视为相同的值。 Suffixing 'f' in your example is redundant and has no effect. 你的例子中的后缀“f”是多余的,没有任何效果。 Since the method closeTo(double, double) has defined the arguments types as double, the passed float values would get promoted to double types implicitly. 由于closeTo(double, double)方法closeTo(double, double)参数类型定义为double,因此传递的float值将隐式提升为double类型。

Since you know you json's value going to be double, So you could expression your assertion as: 既然你知道你的json的值会加倍,那么你可以将你的断言表达为:

get("/price").then().body("price", closeTo(12.12, 0.01));

Depending of the Json parser configuration, non-integer value could be read as BigDecimal, If that is the case, you can use variance of closeTo() as 根据Json解析器配置,非整数值可以读取为BigDecimal,如果是这种情况,则可以使用closeTo()方差作为

.get("/price").then().body("price", 
           closeTo(BigDecimal.valueOf(12.12), BigDecimal.valueOf(0.01)))

Hope it helps. 希望能帮助到你。

If you carefully read Hamcrest then you'll find, it is clearly stated " when the examined object is logically equal to the specified operand " for equalTo . 如果您仔细阅读Hamcrest,那么您会发现, 当被检查对象在逻辑上等于指定的操作数时 ,它会被明确说明为equalTo So obviously it does not matter if it is "5" or 5 ! 所以显然它是“5”还是5并不重要! ANd in Rest-Assured , It is mentioned that equalTo and hasItems are Hamcrest matchers which you should statically import from org.hamcrest.Matchers. Rest-Assured中提到,提到equalTo和hasItems是Hamcrest匹配器,你应该从org.hamcrest.Matchers静态导入。 So I don't think there should be any confusion. 所以我认为不应该有任何混淆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM