如何为 ggplot 绘图编写测试
How to write a test for a ggplot plot
我有很多生成图的函数,通常是 ggplot2。现在,我正在生成绘图并测试基础数据。但我想知道是否有合理的方法来测试情节是否包含我期望的 layers/options 或图形元素是否符合期望。
例如:
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))
})
这就是我卡住的地方
test_that("Plot layers match expectations",{
p <- plot_fun(df)
expect_that(...,...)
})
test_that("Scale is labelled percent",{
p <- plot_fun(df)
expect_that(...,...)
})
也许有更直接的方法?
这似乎是你的目标,当然对绘图参数和内容的具体要求会有所不同。但是对于您在上面精心制作的示例,这些测试应该全部通过:
## 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 为表征 ggplot
对象的其他方法提供了一个很好的起点,以防您有其他想要测试的东西。
值得注意的是,vdiffr 包是为比较绘图而设计的。一个不错的功能是它与 testthat 包集成——它实际上用于在 ggplot2 中进行测试——并且它有一个用于 RStudio 的插件来帮助管理你的测试套件。
除了现有答案之外,我还发现有用的是测试是否可以实际打印绘图。
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
我有很多生成图的函数,通常是 ggplot2。现在,我正在生成绘图并测试基础数据。但我想知道是否有合理的方法来测试情节是否包含我期望的 layers/options 或图形元素是否符合期望。
例如:
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))
})
这就是我卡住的地方
test_that("Plot layers match expectations",{
p <- plot_fun(df)
expect_that(...,...)
})
test_that("Scale is labelled percent",{
p <- plot_fun(df)
expect_that(...,...)
})
也许有更直接的方法?
这似乎是你的目标,当然对绘图参数和内容的具体要求会有所不同。但是对于您在上面精心制作的示例,这些测试应该全部通过:
## 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 为表征 ggplot
对象的其他方法提供了一个很好的起点,以防您有其他想要测试的东西。
值得注意的是,vdiffr 包是为比较绘图而设计的。一个不错的功能是它与 testthat 包集成——它实际上用于在 ggplot2 中进行测试——并且它有一个用于 RStudio 的插件来帮助管理你的测试套件。
除了现有答案之外,我还发现有用的是测试是否可以实际打印绘图。
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