expect_equal() 按一个顺序传递参数,如果交换参数则失败
expect_equal() passes with arguments in one order, fails if arguments are swapped
当尝试将 testthat::expect_equal()
与两个数字和一个公差参数一起使用时,当参数按特定顺序时它通过,但如果两个数字交换参数位置则失败。我注意到这个函数使用基础包中的 all.equal()
引用,并且当参数被交换时该函数也有 pass/fail 差异。
无论两个函数的前两个参数的顺序如何,我都希望得到相同的答案。如果这不是正确的期望,请告诉我。
library(testthat)
# expect_equal does not throw error with one pair of numbers to compare
expect_equal(5, 1, tolerance=1)
# But does when the two numbers are reversed in their arguments
tryCatch(expect_equal(1, 5, tolerance=1), expectation_failure=conditionMessage)
#> [1] "1 not equal to 5.\n1/1 mismatches\n[1] 1 - 5 == -4\n"
# Since this seems to reference `all.equal()` I tried there too, and see an issue:
all.equal(1, 5, tolerance=1)
#> [1] "Mean absolute difference: 4"
all.equal(5, 1, tolerance=1)
#> [1] TRUE
# My session info:
sessionInfo()
#> R version 3.3.3 (2017-03-06)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 7 x64 (build 7601) Service Pack 1
#>
#> locale:
#> [1] LC_COLLATE=English_United States.1252
#> [2] LC_CTYPE=English_United States.1252
#> [3] LC_MONETARY=English_United States.1252
#> [4] LC_NUMERIC=C
#> [5] LC_TIME=English_United States.1252
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] testthat_1.0.2
#>
#> loaded via a namespace (and not attached):
#> [1] backports_1.0.5 R6_2.2.1 magrittr_1.5 rprojroot_1.2
#> [5] tools_3.3.3 htmltools_0.3.6 yaml_2.1.14 crayon_1.3.2
#> [9] Rcpp_0.12.10 stringi_1.1.5 rmarkdown_1.5 knitr_1.15.1
#> [13] stringr_1.2.0 digest_0.6.12 evaluate_0.10
tl;博士
你的容忍度大于
mean(abs(target-current)) / abs(target)
mean(5 - 1) / 5
4 / 5
0.8
所以比较后的函数 returns 0.8 < 1
因为你已经允许它通过了这个容差检查
完整答案
all.equal()
函数有参数 target
和 current
如果深入研究代码,当 target
为 5 且 current
为 1 时,它会计算平均绝对差
mean(abs(target - current))
# 4
然后是目标和公差之间的比较,在本例中是
5 > 1
## TRUE
因为这是真的,它然后计算相对差异
4 / 5
## 0.8
这里0.8不大于公差,所以returns脱离了TRUE
的功能,即
all.equal(5, 1, tolerance = 1)
# [1] TRUE
所以你的tolerance
的值是用来比较相对差异的。这就是为什么公差默认为 1.5e-8
的小值
这里我从all.equal.numeric
中提取了相关代码,只去掉了感兴趣的部分,这样你可以看得更清楚一些
allEqual <- function (target, current, tolerance = sqrt(.Machine$double.eps))
{
msg <- NULL
target <- as.vector(target)
current <- as.vector(current)
out <- is.na(target)
out <- out | target == current
if (all(out))
return(if (is.null(msg)) TRUE else msg)
target <- target[!out]
current <- current[!out]
xy <- mean(abs(target - current))
## THIS BIT HERE vv
what <- {
xn <- mean(abs(target))
# print(paste0("xn: ", xn))
if (is.finite(xn) && xn > tolerance) {
#print("xn (target) is GREATER than the tolerance")
xy <- xy/xn
#print(paste0("relative difference: ", xy))
"relative"
}
else{
# print("xn (target) is SMALLER than the tolerance")
"absolute"
}
}
## THIS BIT HERE ^^
if (is.na(xy) || xy > tolerance)
#print("xy is GREATER than the tolerance")
msg <- c(msg, paste("Mean", what, "difference:", format(xy)))
if (is.null(msg))
TRUE
else msg
}
allEqual(5, 1, tolerance = 0.79)
# [1] "Mean relative difference: 0.8"
allEqual(5, 1, tolerance = 0.81)
# [1] TRUE
allEqual(5, 1, tolerance = 1)
# [1] TRUE
allEqual(1, 5, tolerance = 1)
# [1] "Mean absolute difference: 4"
当尝试将 testthat::expect_equal()
与两个数字和一个公差参数一起使用时,当参数按特定顺序时它通过,但如果两个数字交换参数位置则失败。我注意到这个函数使用基础包中的 all.equal()
引用,并且当参数被交换时该函数也有 pass/fail 差异。
无论两个函数的前两个参数的顺序如何,我都希望得到相同的答案。如果这不是正确的期望,请告诉我。
library(testthat)
# expect_equal does not throw error with one pair of numbers to compare
expect_equal(5, 1, tolerance=1)
# But does when the two numbers are reversed in their arguments
tryCatch(expect_equal(1, 5, tolerance=1), expectation_failure=conditionMessage)
#> [1] "1 not equal to 5.\n1/1 mismatches\n[1] 1 - 5 == -4\n"
# Since this seems to reference `all.equal()` I tried there too, and see an issue:
all.equal(1, 5, tolerance=1)
#> [1] "Mean absolute difference: 4"
all.equal(5, 1, tolerance=1)
#> [1] TRUE
# My session info:
sessionInfo()
#> R version 3.3.3 (2017-03-06)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 7 x64 (build 7601) Service Pack 1
#>
#> locale:
#> [1] LC_COLLATE=English_United States.1252
#> [2] LC_CTYPE=English_United States.1252
#> [3] LC_MONETARY=English_United States.1252
#> [4] LC_NUMERIC=C
#> [5] LC_TIME=English_United States.1252
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] testthat_1.0.2
#>
#> loaded via a namespace (and not attached):
#> [1] backports_1.0.5 R6_2.2.1 magrittr_1.5 rprojroot_1.2
#> [5] tools_3.3.3 htmltools_0.3.6 yaml_2.1.14 crayon_1.3.2
#> [9] Rcpp_0.12.10 stringi_1.1.5 rmarkdown_1.5 knitr_1.15.1
#> [13] stringr_1.2.0 digest_0.6.12 evaluate_0.10
tl;博士
你的容忍度大于
mean(abs(target-current)) / abs(target)
mean(5 - 1) / 5
4 / 5
0.8
所以比较后的函数 returns 0.8 < 1
因为你已经允许它通过了这个容差检查
完整答案
all.equal()
函数有参数 target
和 current
如果深入研究代码,当 target
为 5 且 current
为 1 时,它会计算平均绝对差
mean(abs(target - current))
# 4
然后是目标和公差之间的比较,在本例中是
5 > 1
## TRUE
因为这是真的,它然后计算相对差异
4 / 5
## 0.8
这里0.8不大于公差,所以returns脱离了TRUE
的功能,即
all.equal(5, 1, tolerance = 1)
# [1] TRUE
所以你的tolerance
的值是用来比较相对差异的。这就是为什么公差默认为 1.5e-8
这里我从all.equal.numeric
中提取了相关代码,只去掉了感兴趣的部分,这样你可以看得更清楚一些
allEqual <- function (target, current, tolerance = sqrt(.Machine$double.eps))
{
msg <- NULL
target <- as.vector(target)
current <- as.vector(current)
out <- is.na(target)
out <- out | target == current
if (all(out))
return(if (is.null(msg)) TRUE else msg)
target <- target[!out]
current <- current[!out]
xy <- mean(abs(target - current))
## THIS BIT HERE vv
what <- {
xn <- mean(abs(target))
# print(paste0("xn: ", xn))
if (is.finite(xn) && xn > tolerance) {
#print("xn (target) is GREATER than the tolerance")
xy <- xy/xn
#print(paste0("relative difference: ", xy))
"relative"
}
else{
# print("xn (target) is SMALLER than the tolerance")
"absolute"
}
}
## THIS BIT HERE ^^
if (is.na(xy) || xy > tolerance)
#print("xy is GREATER than the tolerance")
msg <- c(msg, paste("Mean", what, "difference:", format(xy)))
if (is.null(msg))
TRUE
else msg
}
allEqual(5, 1, tolerance = 0.79)
# [1] "Mean relative difference: 0.8"
allEqual(5, 1, tolerance = 0.81)
# [1] TRUE
allEqual(5, 1, tolerance = 1)
# [1] TRUE
allEqual(1, 5, tolerance = 1)
# [1] "Mean absolute difference: 4"