2016-06-16 2 views
4

I ont la fonction suivante:R TryCatch avec testthat attente

fun = function(expr) { 
    mc = match.call() 

    env = as.environment(within(
    list(), 
    expr = eval(mc$expr) 
)) 

    return(env) 
} 

qui est appelée dans un tryCatch() de sorte que toutes les conditions d'erreur dans expr sont traitées avec élégance.

Il fonctionne très bien avec une condition d'erreur standard:

tryCatch({ 
    fun({ 
    stop('error') 
    }) 
}, error = function(e) { 
    message('error happened') 
}) 

# error happened 

Cependant, il ne tient pas compte testthat erreurs d'anticipation (qui est préféré pour mon cas spécifique d'usage):

library(testthat) 

tryCatch({ 
    fun({ 
    expect_true(FALSE) 
    }) 
}, error = function(e) { 
    message('expectation not met') 
}) 

# Error: FALSE isn't true. 

ou plus simplement :

library(testthat) 

tryCatch({ 
    expect_true(FALSE) 
}, error = function(e) { 
    message('expectation not met') 
}) 

# Error: FALSE isn't true. 

L'erreur d'anticipation n'est pas détectée.

Ce problème est apparu après la mise à niveau de R 3.2.2 vers R 3.3.0 - c'est-à-dire que les erreurs d'anticipation ont été interceptées dans R 3.2.2.

Existe-t-il un moyen de faire testthat attentes attrapées par tryCatch() dans R 3.3.0?

+0

Les fonctions '' appel de expect_xxx' expect' qui appelle à son tour 'withRestarts'. Je ne sais pas exactement ce que cela fait, mais cela semble être la racine du problème que vous avez. – Dason

+0

@Dason Oui, j'ai remarqué ça. Je ne suis pas sûr que cela ait toujours été le cas (par exemple lorsque j'ai développé mon code avec R 3.2.2). Idéalement, je préférerais contourner son comportement actuel sans avoir à patcher des singes. – oddHypothesis

Répondre

7

I définir le débogueur sur expect() puis franchit un couple de lignes de code (sortie éditées par souci de brièveté), et a regardé la classe de l'état qui est signalé

> debug(expect) 
> xx = expect_true(FALSE) 
... 
Browse[2]> n 
debug: exp <- as.expectation(exp, ..., srcref = srcref) 
Browse[2]> 
... 
Browse[2]> class(exp) 
[1] "expectation_failure" "expectation"   "condition" 
Browse[2]> Q 
> undebug(expect)  

il est donc pas une condition de de l'erreur «classe, et peut être pris explicitement

> tryCatch(expect_true(FALSE), expectation_failure=conditionMessage) 
[1] "FALSE isn't true.\n" 

Vous pouvez également prendre la classe expectation.

Le redémarrage vous permet de continuer si cela était important.

result <- withCallingHandlers({ 
    expect_true(FALSE) 
    expect_true(!TRUE) 
    expect_true("this sentence") 
}, expectation_failure=function(e) { 
    cat(conditionMessage(e)) 
    invokeRestart("continue_test") 
}) 

avec sortie

FALSE isn't true. 
!TRUE isn't true. 
"this sentence" isn't true. 
> result 
[1] FALSE 

On pourrait également prendre ou gérer les succès

> tryCatch(expect_true(TRUE), expectation_success=class) 
[1] "expectation_success" "expectation"   "condition" 
+0

Merci! La documentation 'tryCatch()' ne m'indiquait certainement pas clairement que vous pouviez spécifier des gestionnaires pour des classes spécifiques. Un autre à ajouter à ma liste de trucs R. – oddHypothesis