2015-06-24 13 views
24

Mam wiele funkcji generujących wykresy, zazwyczaj z ggplot2. Właśnie teraz generuję wykres i testuję podstawowe dane. Ale chciałbym się dowiedzieć, czy istnieje rozsądny sposób przetestowania, czy fabuła zawiera warstwy/opcje, których się spodziewam, lub czy elementy graficzne pasują do oczekiwań.Jak napisać test dla wykresu ggplot?

Na przykład:

library(ggplot2) 
library(scales) # for percent() 
library(testthat) 

df <- data.frame(
    Response = LETTERS[1:5], 
    Proportion = c(0.1,0.2,0.1,0.2,0.4) 
) 

#' @export plot_fun 
plot_fun <- function(df) { 
    p1 <- ggplot(df, aes(Response, Proportion)) + 
    geom_bar(stat='identity') + 
    scale_y_continuous(labels = percent) 
return(p1) 
} 

test_that("Plot returns ggplot object",{ 
    p <- plot_fun(df) 
    expect_is(p,"ggplot") 
}) 

test_that("Plot uses correct data", { 
    p <- plot_fun(df) 
    expect_that(df, equals(p$data)) 

}) 

To gdzie utknąłem

test_that("Plot layers match expectations",{ 
    p <- plot_fun(df) 
    expect_that(...,...) 
}) 

test_that("Scale is labelled percent",{ 
    p <- plot_fun(df) 
    expect_that(...,...) 
}) 

Być może istnieje bardziej bezpośrednie podejście?

+0

ggplot2 [repo] (https://github.com/hadley/ggplot2/blob/master/tests/test-all.R) nie ma testów, więc może to nie jest realizowany? Byłby miłym dodatkiem. – jeremycg

+1

Jestem świadomy, stąd pytanie - i przychodzące nagrody. –

+3

[This] (https://github.com/wch/ggplot2/wiki) może być przydatny, chociaż nie jestem pewien, jak wiele rozwoju zestaw testów wizualnych uzyskał od czasu jego wdrożenia. – joran

Odpowiedz

14

To wydaje się być tym, do czego zmierzasz, chociaż szczegółowe wymagania dotyczące drukowania parametrów i zawartości będą oczywiście różne. Ale na przykład ty ładnie wykonane powyżej tych testów powinny przechodzić:

## Load the proto library for accessing sub-components of the ggplot2 
## plot objects: 
library(proto) 

test_that("Plot layers match expectations",{ 
    p <- plot_fun(df) 
    expect_is(p$layers[[1]], "proto") 
    expect_identical(p$layers[[1]]$geom$objname, "bar") 
    expect_identical(p$layers[[1]]$stat$objname, "identity") 
}) 

test_that("Scale is labelled 'Proportion'",{ 
    p <- plot_fun(df) 
    expect_identical(p$labels$y, "Proportion") 
}) 

test_that("Scale range is NULL",{ 
    p <- plot_fun(df) 
    expect_null(p$scales$scales[[1]]$range$range) 
}) 

question and its answers ta oferta to dobry punkt wyjścia na inne sposoby, aby scharakteryzować ggplot obiektów w przypadku gdy masz inne rzeczy, które chcesz przetestować.

4

Warto zauważyć, że pakiet vdiffr jest przeznaczony do porównywania działek. Ciekawą cechą jest to, że integruje się z pakietem testthat - w rzeczywistości jest używany do testowania w ggplot2 - i ma dodatek do RStudio, aby pomóc w zarządzaniu testsuite.

1

To, co również uważam za użyteczne oprócz istniejących odpowiedzi, to sprawdzenie, czy fabuła może zostać wydrukowana.

library(ggplot2) 
library(scales) # for percent() 
library(testthat) 

# First, 'correct' data frame 
df <- data.frame(
    Response = LETTERS[1:5], 
    Proportion = c(0.1,0.2,0.1,0.2,0.4) 
) 

# Second data frame where column has 'wrong' name that does not match aes() 
df2 <- data.frame(
    x   = LETTERS[1:5], 
    Proportion = c(0.1,0.2,0.1,0.2,0.4) 
) 

plot_fun <- function(df) { 
    p1 <- ggplot(df, aes(Response, Proportion)) + 
     geom_bar(stat='identity') + 
     scale_y_continuous(labels = percent) 
    return(p1) 
} 

# All tests succeed 
test_that("Scale is labelled 'Proportion'",{ 
    p <- plot_fun(df) 
    expect_true(is.ggplot(p)) 
    expect_identical(p$labels$y, "Proportion") 

    p <- plot_fun(df2) 
    expect_true(is.ggplot(p)) 
    expect_identical(p$labels$y, "Proportion") 
}) 

# Second test with data frame df2 fails 
test_that("Printing ggplot object actually works",{ 
    p <- plot_fun(df) 
    expect_error(print(p), NA) 

    p <- plot_fun(df2) 
    expect_error(print(p), NA) 
}) 
#> Error: Test failed: 'Printing ggplot object actually works' 
#> * `print(p)` threw an error. 
#> Message: object 'Response' not found 
#> Class: simpleError/error/condition 
Powiązane problemy