【问题标题】:expect_equal() passes with arguments in one order, fails if arguments are swappedexpect_equal() 以一种顺序传递参数,如果交换参数则失败
【发布时间】:2017-07-12 18:58:46
【问题描述】:

当尝试将testthat::expect_equal() 与两个数字和一个容差参数一起使用时,它会在参数按特定顺序排列时通过,但如果两个数字交换参数位置则失败。我注意到这个函数使用基本包中的all.equal() 引用,并且该函数在交换参数时也有通过/失败的区别。

无论两个函数的前两个参数的顺序如何,我都希望得到相同的答案。如果这不是正确的期望,请告诉我。

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

【问题讨论】:

    标签: r testthat


    【解决方案1】:

    tl;博士

    你的容忍度大于

    mean(abs(target-current)) / abs(target)
    mean(5 - 1) / 5
    4 / 5
    0.8  
    

    所以函数在比较 0.8 < 1 之后返回,因为你允许它通过这个容差检查


    完整答案

    all.equal() 函数有参数targetcurrent

    如果您深入研究代码,当target 为 5 而current 为 1 时,它会计算平均绝对差

    mean(abs(target - current))
    # 4
    

    然后是目标和公差之间的比较,在这种情况下是

    5 > 1
    ## TRUE
    

    因为这是 TRUE,所以它会计算相对差异

    4 / 5 
    ## 0.8
    

    这里,0.8不大于公差,所以它以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"
    

    【讨论】:

    • 谢谢,太好了!我误读/误解了all.equal() 文档,并认为如果scale=NULL(默认),则使用绝对比较。仅当 targetcurrent 接近 0 时才适用。在我的实际代码中,我改为使用 expect_true() 并将 abs 差异与设定的容差进行比较以满足我的需要,而不是 expect_equal() 被误解公差值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多