2013-01-23 8 views
6

Bir R paketi için bazı testler yazıyorum ve R CMD check olmasını istiyorum, bazı girişler için işlevlerin doğru uyarıları görüntülediğini doğrulayın. Ancak uyarıyı nasıl çıkaracağımı anlayamıyorum, böylece test edebilirim.Uyarı doğru bir şekilde atılıp atılmadığını görmek için R'de bir paket testi nasıl yazılır?

Ben Yani eğer böyle bir işlevi: options değiştirerek

warningOutput <-try(throwsWarning(1)) 
if (warningOutput!='Argument "x" is greater than zero, results may be incorrect'){ 
    stop('function "throwsWarning" did not produce correct warning when x>0') 
} 

Şimdiye kadar bulduğum mümkün kısmi çözümlerin: Ben gibi benim test dosyasındaki bir şey ister ki

throwsWarning<-function(x){ 
    if(x>0){ 
    warning('Argument "x" is greater than zero, results may be incorrect') 
    } 
    # do something useful ... 
} 

böylece uyarılar trycatch bloğu ile hatalar ve çevre olarak ele alınır. Ayrıca last.warning test değeri olarak kabul edilir, ancak uyarı atılmazsa (önceki değeri test eder) tehlikeli görünmektedir. Eksik olduğumu yapmanın kolay bir yolu olmalı mı?

+1

Testlerde 'testthat 'kullanıyor görünmüyorsunuz. – Spacedman

cevap

6

testthat package, kullanabileceğiniz expect_warning ve gives_warning işlevine sahiptir. örneklerden

, böyle bir şey yapacağını:

R> library(testthat) 
R> expect_that(warning("this is a warning"), gives_warning("is a")) 
## This does not raise an error, but: 
R> expect_that(warning("this is a warning"), gives_warning("nope")) 
Error: warning("this is a warning") does not match 'nope'. Actual value: 
this is a warning 

Yani, gives_warning yayılan olması gerekiyordu uyarı karşılaştırıldıkça düzenli ifadedir. Normal ifade uyuşmuyorsa (veya uyarı verilmezse), kırmızı bir bayrak kaldırılır. kullanarak Eşit

, kısa expect_warning: Kendi paketini yazıyorsanız, bu hataları ve uyarıları içeren belirli türleri atma (ve alıcı) tarafından R'ın durum sistemin faydalanmak için mantıklı olabilir

R> expect_warning(warning("this is a warning"), "is a") 
+1

Güzel! Testleri bu kadar test olmadan yazdığına inanamıyorum. CRAN, paket yazım dokümanlarında önerdiği takdirde harika olurdu. Tek dezavantajı sadece testleri çalıştırmak için fazladan bağımlılık eklemek gibi görünüyor. – skyebend

+0

Radarınızda olmayan bir pakete sizi uyarladığınıza memnun oldum - özellikle söz konusu paket tamamen harika olduğu için ;-) Ayrıca, 'Test' alanına 'testthat' yazın - gerek yok 'Depends' veya 'Imports' içinde olmak için, sadece testleri çalıştırmak isteyen kişiler için (sadece paketinizi kullanmak isteyen kişiler için değil) pakete bağımlılık eklemiş olursunuz. –

2

. Yani

myFun <- function(x) { 
    if (any(is.na(x))) { 
     w <- simpleWarning("'x' contains NA values") 
     class(w) <- c("HasNA", class(w)) 
     warning(w) 
    } 
    if (any(x < 0)) 
     warning("'x' contains values less than 0") 
    x 
} 

ve sonra library(RUnit) ile test örneğin içinde, tryCatch kullanmak ve sınıf HasNA ile, uyarıları yani test yalnızca ilgilendiğiniz koşulları, koparmak:

test_myFun_NAwarning <- function() { 
    warnOccurred <- FALSE 
    tryCatch(myFun(1:5), HasNA = function(w) warnOcccurred <<- TRUE) 
    checkTrue(!warnOccurred) 
    tryCatch(myFun(-(1:5)), HasNA = function(w) warnOcccurred <<- TRUE) 
    checkTrue(!warnOccurred) 
    tryCatch(myFun(c(1:5, NA)), HasNA = function(w) warnOccurred <<- TRUE) 
    checkTrue(warnOccurred) 
} 

lider tryCatch ilgilendiğiniz sadece belirli uyarı alıcı ve wa bunu yaparken göstermektedir

> test_myFun_NAwarning() 
[1] TRUE 
Warning message: 
In myFun(-(1:5)) : 'x' contains values less than 0 

için Bu, dizenin metniyle eşleşmiyor. Belki de paketiniz için tüm uyarıları yapmak için .warn yardımcı işlevine sahip olabilirsiniz. Daha fazla ayrıntı için bkz. ?withCallingHandlers; withCallingHandlers ve muffleRestart, bir uyarıdan sonra tryCatch yolunu durdurmak yerine, devam eden değerlendirmeyle nasıl başa çıkabilir.

İlgili konular