简体   繁体   English

如何为ggplot图编写测试

[英]How to write a test for a ggplot plot

I have a lot of functions that generate plots, typically with ggplot2. 我有很多生成绘图的函数,通常使用ggplot2。 Right now, I'm generating the plot and testing the underlying data. 现在,我正在生成情节并测试基础数据。 But I'd like to know if there's a reasonable way to test that the plot contains the layers/options I expect it to or that graphical elements match expectations. 但我想知道是否有合理的方法来测试该图包含我期望的图层/选项或图形元素是否符合预期。

For example: 例如:

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))

})

This is where I'm stuck 这就是我被困住的地方

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

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

Perhaps there's a more direct approach? 也许有更直接的方法?

This seems to be what you're aiming at, though specific requirements for plotting parameters and contents will vary of course. 这似乎是你的目标,虽然绘制参数和内容的具体要求当然会有所不同。 But for the example you nicely crafted above these tests should all pass: 但是对于你在这些测试之上精心设计的例子应该全部通过:

##  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)
})

This question and its answers offer a good starting point on other ways to characterize ggplot objects in case you have other things you'd like to test. 这个问题及其答案为其他表征ggplot对象的方法提供了一个很好的起点,以防你有其他想要测试的东西。

It's worth noting that the vdiffr package is designed for comparing plots. 值得注意的是, vdiffr软件包是为比较图而设计的。 A nice feature is that it integrates with the testthat package -- it's actually used for testing in ggplot2 -- and it has an add-in for RStudio to help manage your testsuite. 一个很好的功能是它与testthat软件包集成 - 它实际上用于在ggplot2中进行测试 - 它有一个RStudio的插件来帮助管理你的测试套件。

What I also find useful in addition to the existing answers, is to test if a plot can actually be printed. 除了现有答案之外,我还发现有用的是测试是否可以实际打印图表。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM