From b84ba74f1bfe3eb9b2ca6ec5815a49b7aac9d838 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Sat, 15 Jun 2024 16:09:01 -0500 Subject: [PATCH 1/4] Inline test files directly into tests --- DESCRIPTION | 2 +- tests/testthat/_snaps/errors.md | 8 ++ tests/testthat/comment.R | 2 - tests/testthat/data.R | 2 - tests/testthat/error-complex.R | 5 - tests/testthat/error.R | 2 - tests/testthat/example-1.R | 22 ---- tests/testthat/ggplot-empty-1.R | 4 - tests/testthat/ggplot-empty-2.R | 4 - tests/testthat/ggplot-loop.R | 6 -- tests/testthat/ggplot.R | 2 - tests/testthat/helper.R | 8 ++ tests/testthat/interleave-1.R | 4 - tests/testthat/interleave-2.R | 4 - tests/testthat/order.R | 16 --- tests/testthat/parse.R | 6 -- tests/testthat/plot-additions.R | 2 - tests/testthat/plot-clip.R | 3 - tests/testthat/plot-last-comment.R | 4 - tests/testthat/plot-loop.R | 4 - tests/testthat/plot-multi-layout.R | 7 -- tests/testthat/plot-multi-layout2.R | 9 -- tests/testthat/plot-multi-missing.R | 4 - tests/testthat/plot-multi.R | 5 - tests/testthat/plot-new.R | 5 - tests/testthat/plot-par.R | 3 - tests/testthat/plot-par2.R | 5 - tests/testthat/plot-persp.R | 8 -- tests/testthat/plot-strwidth.R | 4 - tests/testthat/plot.R | 1 - tests/testthat/raw-output.R | 4 - tests/testthat/test-errors.R | 22 +++- tests/testthat/test-evaluate.R | 45 +++++++-- tests/testthat/test-graphics.R | 151 ++++++++++++++++++++++------ tests/testthat/test-output.R | 2 +- tests/testthat/try.R | 4 - 36 files changed, 188 insertions(+), 201 deletions(-) create mode 100644 tests/testthat/_snaps/errors.md delete mode 100644 tests/testthat/comment.R delete mode 100644 tests/testthat/data.R delete mode 100644 tests/testthat/error-complex.R delete mode 100644 tests/testthat/error.R delete mode 100644 tests/testthat/example-1.R delete mode 100644 tests/testthat/ggplot-empty-1.R delete mode 100644 tests/testthat/ggplot-empty-2.R delete mode 100644 tests/testthat/ggplot-loop.R delete mode 100644 tests/testthat/ggplot.R create mode 100644 tests/testthat/helper.R delete mode 100644 tests/testthat/interleave-1.R delete mode 100644 tests/testthat/interleave-2.R delete mode 100644 tests/testthat/order.R delete mode 100644 tests/testthat/parse.R delete mode 100644 tests/testthat/plot-additions.R delete mode 100644 tests/testthat/plot-clip.R delete mode 100644 tests/testthat/plot-last-comment.R delete mode 100644 tests/testthat/plot-loop.R delete mode 100644 tests/testthat/plot-multi-layout.R delete mode 100644 tests/testthat/plot-multi-layout2.R delete mode 100644 tests/testthat/plot-multi-missing.R delete mode 100644 tests/testthat/plot-multi.R delete mode 100644 tests/testthat/plot-new.R delete mode 100644 tests/testthat/plot-par.R delete mode 100644 tests/testthat/plot-par2.R delete mode 100644 tests/testthat/plot-persp.R delete mode 100644 tests/testthat/plot-strwidth.R delete mode 100644 tests/testthat/plot.R delete mode 100644 tests/testthat/raw-output.R delete mode 100644 tests/testthat/try.R diff --git a/DESCRIPTION b/DESCRIPTION index a85039ce..dbb1b24b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -28,7 +28,7 @@ Imports: methods Suggests: covr, - ggplot2, + ggplot2 (>= 3.3.6), lattice, rlang, testthat (>= 3.0.0), diff --git a/tests/testthat/_snaps/errors.md b/tests/testthat/_snaps/errors.md new file mode 100644 index 00000000..0a97eddb --- /dev/null +++ b/tests/testthat/_snaps/errors.md @@ -0,0 +1,8 @@ +# code errors if stop_on_error == 2L + + Code + evaluate("stop(\"1\")", stop_on_error = 2L) + Condition + Error: + ! 1 + diff --git a/tests/testthat/comment.R b/tests/testthat/comment.R deleted file mode 100644 index ca63e33f..00000000 --- a/tests/testthat/comment.R +++ /dev/null @@ -1,2 +0,0 @@ -# This test case contains no executable code -# but it shouldn't throw an error diff --git a/tests/testthat/data.R b/tests/testthat/data.R deleted file mode 100644 index fd772172..00000000 --- a/tests/testthat/data.R +++ /dev/null @@ -1,2 +0,0 @@ -data(barley, package = "lattice") -barley diff --git a/tests/testthat/error-complex.R b/tests/testthat/error-complex.R deleted file mode 100644 index 7df4d244..00000000 --- a/tests/testthat/error-complex.R +++ /dev/null @@ -1,5 +0,0 @@ -f <- function() g() -g <- function() h() -h <- function() stop("Error") - -f() diff --git a/tests/testthat/error.R b/tests/testthat/error.R deleted file mode 100644 index cf133e16..00000000 --- a/tests/testthat/error.R +++ /dev/null @@ -1,2 +0,0 @@ -stop("1") -2 diff --git a/tests/testthat/example-1.R b/tests/testthat/example-1.R deleted file mode 100644 index a2a58e0a..00000000 --- a/tests/testthat/example-1.R +++ /dev/null @@ -1,22 +0,0 @@ -# These test cases check that interweave -# works for a variety of situations - -a <- 1 # Comment after an expression -b <- 2 - -{ - a - b -} - -# Here is a comment which should be followed -# by two new lines - -{ - print(a) # comment in a block - print(b) -} - -a; b - -a; b # Comment diff --git a/tests/testthat/ggplot-empty-1.R b/tests/testthat/ggplot-empty-1.R deleted file mode 100644 index 704d961e..00000000 --- a/tests/testthat/ggplot-empty-1.R +++ /dev/null @@ -1,4 +0,0 @@ -suppressPackageStartupMessages(library(ggplot2)) -ggplot(iris) + - aes(x = Speciess, y = Sepal.Length) + - geom_boxplot() diff --git a/tests/testthat/ggplot-empty-2.R b/tests/testthat/ggplot-empty-2.R deleted file mode 100644 index 15745561..00000000 --- a/tests/testthat/ggplot-empty-2.R +++ /dev/null @@ -1,4 +0,0 @@ -suppressPackageStartupMessages(library(ggplot2)) -ggplot(iris) + - aes(x = Species, y = Sepal.Length) + - geom_bar() diff --git a/tests/testthat/ggplot-loop.R b/tests/testthat/ggplot-loop.R deleted file mode 100644 index 59d8a122..00000000 --- a/tests/testthat/ggplot-loop.R +++ /dev/null @@ -1,6 +0,0 @@ -suppressPackageStartupMessages(library(ggplot2)) -for (j in 1:2) { - # ggplot2 has been loaded previously - print(ggplot(data.frame(x = rnorm(30), y = runif(30)), aes(x, y)) + geom_point()) -} - diff --git a/tests/testthat/ggplot.R b/tests/testthat/ggplot.R deleted file mode 100644 index e631ab2f..00000000 --- a/tests/testthat/ggplot.R +++ /dev/null @@ -1,2 +0,0 @@ -suppressPackageStartupMessages(library(ggplot2)) -ggplot(mtcars, aes(mpg, wt)) + geom_point() diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R new file mode 100644 index 00000000..4091f6a6 --- /dev/null +++ b/tests/testthat/helper.R @@ -0,0 +1,8 @@ +evaluate_ <- function(text, ...) { + # Trim off leading/trailing new lines and dedent + text <- gsub("^\n {4}", "", text) + text <- gsub("\n {4}", "\n", text) + text <- gsub("\n +$", "", text) + + evaluate(text, ...) +} diff --git a/tests/testthat/interleave-1.R b/tests/testthat/interleave-1.R deleted file mode 100644 index 59042732..00000000 --- a/tests/testthat/interleave-1.R +++ /dev/null @@ -1,4 +0,0 @@ -for (i in 1:2) { - cat(i) - plot(i) -} diff --git a/tests/testthat/interleave-2.R b/tests/testthat/interleave-2.R deleted file mode 100644 index af03d330..00000000 --- a/tests/testthat/interleave-2.R +++ /dev/null @@ -1,4 +0,0 @@ -for (i in 1:2) { - plot(i) - cat(i) -} diff --git a/tests/testthat/order.R b/tests/testthat/order.R deleted file mode 100644 index 852dc602..00000000 --- a/tests/testthat/order.R +++ /dev/null @@ -1,16 +0,0 @@ -cat("1\n") -print("2") -warning("3") -print("4") -message("5") -stop("6") -stop("7", call. = FALSE) - -f <- function(x) { - print("8") - message("9") - warning("10") - stop("11") -} -f() - diff --git a/tests/testthat/parse.R b/tests/testthat/parse.R deleted file mode 100644 index efc95a5a..00000000 --- a/tests/testthat/parse.R +++ /dev/null @@ -1,6 +0,0 @@ -f <- function() { - for (i in 1:3) { - plot(rnorm(100)) - lines(rnorm(100)) - } -} diff --git a/tests/testthat/plot-additions.R b/tests/testthat/plot-additions.R deleted file mode 100644 index 253b6f9b..00000000 --- a/tests/testthat/plot-additions.R +++ /dev/null @@ -1,2 +0,0 @@ -plot(1:10) -lines(1:10) diff --git a/tests/testthat/plot-clip.R b/tests/testthat/plot-clip.R deleted file mode 100644 index 1246cef6..00000000 --- a/tests/testthat/plot-clip.R +++ /dev/null @@ -1,3 +0,0 @@ -plot(rnorm(100), rnorm(100)) -clip(-1, 1, -1, 1) -points(rnorm(100), rnorm(100), col = 'red') diff --git a/tests/testthat/plot-last-comment.R b/tests/testthat/plot-last-comment.R deleted file mode 100644 index 2bbd4354..00000000 --- a/tests/testthat/plot-last-comment.R +++ /dev/null @@ -1,4 +0,0 @@ -par(mfrow = c(3, 3)) -for (i in 1:7) - image(volcano) -# comment diff --git a/tests/testthat/plot-loop.R b/tests/testthat/plot-loop.R deleted file mode 100644 index 10342e06..00000000 --- a/tests/testthat/plot-loop.R +++ /dev/null @@ -1,4 +0,0 @@ -for (i in 1:3) { - plot(rnorm(100)) -} - diff --git a/tests/testthat/plot-multi-layout.R b/tests/testthat/plot-multi-layout.R deleted file mode 100644 index 41fb3d57..00000000 --- a/tests/testthat/plot-multi-layout.R +++ /dev/null @@ -1,7 +0,0 @@ -for (j in 1:3) { - layout(matrix(c(1, 2, 1, 3, 4, 4), 3, 2, byrow = TRUE)) - plot(rnorm(10)) - plot(rnorm(10)) - plot(rnorm(10)) - plot(rnorm(10)) -} diff --git a/tests/testthat/plot-multi-layout2.R b/tests/testthat/plot-multi-layout2.R deleted file mode 100644 index 20d12805..00000000 --- a/tests/testthat/plot-multi-layout2.R +++ /dev/null @@ -1,9 +0,0 @@ -layout(matrix(c(1, 2, 1, 3, 4, 4), 3, 2, byrow = TRUE)) -# another expression before drawing the plots -x <- 1 + 1 -for (j in 1:2) { - plot(rnorm(10)) - plot(rnorm(10)) - plot(rnorm(10)) - plot(rnorm(10)) -} diff --git a/tests/testthat/plot-multi-missing.R b/tests/testthat/plot-multi-missing.R deleted file mode 100644 index 402a9747..00000000 --- a/tests/testthat/plot-multi-missing.R +++ /dev/null @@ -1,4 +0,0 @@ -par(mfrow = c(2, 2)) -plot(1) -plot(2) -plot(3) diff --git a/tests/testthat/plot-multi.R b/tests/testthat/plot-multi.R deleted file mode 100644 index 6ab65579..00000000 --- a/tests/testthat/plot-multi.R +++ /dev/null @@ -1,5 +0,0 @@ -par(mfrow = c(2, 2)) -plot(1) -plot(2) -plot(3) -plot(4) diff --git a/tests/testthat/plot-new.R b/tests/testthat/plot-new.R deleted file mode 100644 index 73782602..00000000 --- a/tests/testthat/plot-new.R +++ /dev/null @@ -1,5 +0,0 @@ -plot.new() -plot(1:10) -plot.new() -plot(1:10) -plot.new() diff --git a/tests/testthat/plot-par.R b/tests/testthat/plot-par.R deleted file mode 100644 index ada66433..00000000 --- a/tests/testthat/plot-par.R +++ /dev/null @@ -1,3 +0,0 @@ -plot(1) -par(mar = rep(0, 4)) -plot(2) diff --git a/tests/testthat/plot-par2.R b/tests/testthat/plot-par2.R deleted file mode 100644 index e56c85c6..00000000 --- a/tests/testthat/plot-par2.R +++ /dev/null @@ -1,5 +0,0 @@ -barplot(table(mtcars$mpg), main = "All") -# should capture all plots in this loop -for (numcyl in levels(as.factor(mtcars$cyl))) { - barplot(table(mtcars$mpg[mtcars$cyl == numcyl]), main = paste("cyl = ", numcyl)) -} diff --git a/tests/testthat/plot-persp.R b/tests/testthat/plot-persp.R deleted file mode 100644 index fd930539..00000000 --- a/tests/testthat/plot-persp.R +++ /dev/null @@ -1,8 +0,0 @@ -x <- seq(-10, 10, length = 30) -y <- x -ff <- function(x,y) { r <- sqrt(x^2 + y^2); 10 * sin(r) / r } -z <- outer(x, y, ff) -z[is.na(z)] <- 1 -for (i in 1:3) { - persp(x, y, z, phi = 30 + i * 10, theta = 30) -} diff --git a/tests/testthat/plot-strwidth.R b/tests/testthat/plot-strwidth.R deleted file mode 100644 index 3739b982..00000000 --- a/tests/testthat/plot-strwidth.R +++ /dev/null @@ -1,4 +0,0 @@ -x <- strwidth('foo', 'inches') -y <- strheight('foo', 'inches') -par(mar = c(4, 4, 1, 1)) -plot(1) diff --git a/tests/testthat/plot.R b/tests/testthat/plot.R deleted file mode 100644 index e6e140b9..00000000 --- a/tests/testthat/plot.R +++ /dev/null @@ -1 +0,0 @@ -plot(1:10) diff --git a/tests/testthat/raw-output.R b/tests/testthat/raw-output.R deleted file mode 100644 index 1f445125..00000000 --- a/tests/testthat/raw-output.R +++ /dev/null @@ -1,4 +0,0 @@ -rnorm(10) -x <- list("I'm a list!") -suppressPackageStartupMessages(library(ggplot2)) -ggplot(mtcars, aes(mpg, wt)) + geom_point() diff --git a/tests/testthat/test-errors.R b/tests/testthat/test-errors.R index 274f439d..9dd6510d 100644 --- a/tests/testthat/test-errors.R +++ b/tests/testthat/test-errors.R @@ -1,19 +1,25 @@ test_that("all code run, even after error", { - ev <- evaluate(file("error.R")) + ev <- evaluate_('stop("1")\n2') expect_length(ev, 4) }) test_that("code aborts on error if stop_on_error == 1L", { - ev <- evaluate(file("error.R"), stop_on_error = 1L) + ev <- evaluate('stop("1")\n2', stop_on_error = 1L) expect_length(ev, 2) }) test_that("code errors if stop_on_error == 2L", { - expect_error(evaluate(file("error.R"), stop_on_error = 2L), "1") + expect_snapshot(evaluate('stop("1")', stop_on_error = 2L), error = TRUE) }) test_that("traceback useful if stop_on_error == 2L", { - expect_error(evaluate(file("error-complex.R"), stop_on_error = 2L), "Error") + expect_error(evaluate_(' + f <- function() g() + g <- function() h() + h <- function() stop("Error") + + f() + ', stop_on_error = 2L), "Error") ## Doesn't work because .Traceback not create when code run ## inside try or tryCatch. Can't figure out how to work around. @@ -26,6 +32,12 @@ test_that("traceback useful if stop_on_error == 2L", { }) test_that("capture messages in try() (#88)", { - ev <- evaluate(file("try.R")) + # TODO: figure out why this doesn't work interactively + ev <- evaluate_(' + g <- function() f("error") + f <- function(x) stop(paste0("Obscure ", x)) + + try(g()) + ') expect_match(ev[[length(ev)]], "Obscure error") }) diff --git a/tests/testthat/test-evaluate.R b/tests/testthat/test-evaluate.R index e607d74d..8d186e19 100644 --- a/tests/testthat/test-evaluate.R +++ b/tests/testthat/test-evaluate.R @@ -1,5 +1,8 @@ test_that("file with only comments runs", { - ev <- evaluate(file("comment.R")) + ev <- evaluate_(" + # This test case contains no executable code + # but it shouldn't throw an error + ") expect_length(ev, 2) expect_equal(classes(ev), c("source", "source")) @@ -8,7 +11,10 @@ test_that("file with only comments runs", { test_that("data sets loaded", { skip_if_not_installed("lattice") - ev <- evaluate(file("data.R")) + ev <- evaluate_(' + data(barley, package = "lattice") + barley + ') expect_length(ev, 3) }) @@ -62,21 +68,38 @@ test_that("options(warn = 0) and options(warn = 1) produces warnings", { # }) test_that("output and plots interleaved correctly", { - ev <- evaluate(file("interleave-1.R")) - expect_equal(classes(ev), - c("source", "character", "recordedplot", "character", "recordedplot")) + ev <- evaluate_(" + for (i in 1:2) { + cat(i) + plot(i) + } + ") + expect_equal( + classes(ev), + c("source", "character", "recordedplot", "character", "recordedplot") + ) - ev <- evaluate(file("interleave-2.R")) - expect_equal(classes(ev), - c("source", "recordedplot", "character", "recordedplot", "character")) + ev <- evaluate_(" + for (i in 1:2) { + plot(i) + cat(i) + } + ") + expect_equal( + classes(ev), + c("source", "recordedplot", "character", "recordedplot", "character") + ) }) test_that("return value of value handler inserted directly in output list", { skip_if_not_installed("ggplot2") - ev <- evaluate( - file("raw-output.R"), - output_handler = new_output_handler(value = identity) + ev <- evaluate_(' + rnorm(10) + x <- list("I\'m a list!") + suppressPackageStartupMessages(library(ggplot2)) + ggplot(mtcars, aes(mpg, wt)) + geom_point() + ', output_handler = new_output_handler(value = identity) ) expect_equal( classes(ev), diff --git a/tests/testthat/test-graphics.R b/tests/testthat/test-graphics.R index 57687642..0cb973b3 100644 --- a/tests/testthat/test-graphics.R +++ b/tests/testthat/test-graphics.R @@ -1,19 +1,27 @@ test_that("single plot is captured", { - ev <- evaluate(file("plot.R")) + ev <- evaluate("plot(1:10)") expect_length(ev, 2) expect_equal(classes(ev), c("source", "recordedplot")) }) test_that("ggplot is captured", { + # TODO: figure out why this doesn't work interactively: probably because + # the root environment is wrong - needs to be parent of global env skip_if_not_installed("ggplot2") - ev <- evaluate(file("ggplot.R")) + ev <- evaluate_(" + suppressPackageStartupMessages(library(ggplot2)) + ggplot(mtcars, aes(mpg, wt)) + geom_point() + ") expect_length(ev, 3) expect_equal(classes(ev), c("source", "source", "recordedplot")) }) test_that("plot additions are captured", { - ev <- evaluate(file("plot-additions.R")) + ev <- evaluate_(" + plot(1:10) + lines(1:10) + ") expect_length(ev, 4) expect_equal( @@ -23,64 +31,114 @@ test_that("plot additions are captured", { }) test_that("blank plots by plot.new() are preserved", { - ev <- evaluate(file("plot-new.R")) + ev <- evaluate_(" + plot.new() + plot(1:10) + plot.new() + plot(1:10) + plot.new() + ") expect_length(ev, 10) - - expect_equal( - classes(ev), - rep(c("source", "recordedplot"), 5) - ) + expect_equal(classes(ev), rep(c("source", "recordedplot"), 5)) }) test_that("base plots in a single expression are captured", { - ev <- evaluate(file("plot-loop.R")) + ev <- evaluate_(" + for (i in 1:3) { + plot(rnorm(100)) + } + ") expect_length(ev, 4) - expect_equal(classes(ev), c("source", rep("recordedplot", 3))) }) test_that("ggplot2 plots in a single expression are captured", { skip_if_not_installed("ggplot2") - ev <- evaluate(file("ggplot-loop.R")) + ev <- evaluate_(" + suppressPackageStartupMessages(library(ggplot2)) + for (j in 1:2) { + # ggplot2 has been loaded previously + print(ggplot(data.frame(x = rnorm(30), y = runif(30)), aes(x, y)) + geom_point()) + } + ") expect_length(ev, 4) expect_equal(classes(ev), c(rep("source", 2), rep("recordedplot", 2))) }) -test_that("Empty ggplot should not be recorded", { +test_that("erroring ggplots should not be recorded", { skip_if_not_installed("ggplot2") - ev <- evaluate(file(test_path("ggplot-empty-1.R"))) - expect_identical(classes(ev), c( - "source", "source", - if (packageVersion("ggplot2") > "3.3.6") "rlang_error" else "simpleError" - )) - ev <- evaluate(file(test_path("ggplot-empty-2.R"))) + + # error in aesthetics + ev <- evaluate_(" + suppressPackageStartupMessages(library(ggplot2)) + ggplot(iris) + aes(XXXXXXXXXX, Sepal.Length) + geom_boxplot() + ") + expect_identical(classes(ev), c("source", "source", "rlang_error")) + + # error in geom + ev <- evaluate_(" + suppressPackageStartupMessages(library(ggplot2)) + ggplot(iris) + aes(Species, Sepal.Length) + geom_bar() + ") expect_identical(classes(ev), c("source", "source", "rlang_error")) }) test_that("multirow graphics are captured only when complete", { - ev <- evaluate(file("plot-multi.R")) - + ev <- evaluate_(" + par(mfrow = c(2, 2)) + plot(1) + plot(2) + plot(3) + plot(4) + ") expect_equal(classes(ev), c(rep("source", 5), "recordedplot")) }) test_that("multirow graphics are captured on close", { - ev <- evaluate(file("plot-multi-missing.R")) + ev <- evaluate_(" + par(mfrow = c(2, 2)) + plot(1) + plot(2) + plot(3) + ") expect_equal(classes(ev), c(rep("source", 4), "recordedplot")) }) test_that("plots are captured in a non-rectangular layout", { - ev <- evaluate(file("plot-multi-layout.R")) + ev <- evaluate_(" + for (j in 1:3) { + layout(matrix(c(1, 2, 1, 3, 4, 4), 3, 2, byrow = TRUE)) + plot(rnorm(10)) + plot(rnorm(10)) + plot(rnorm(10)) + plot(rnorm(10)) + } + ") expect_equal(classes(ev), rep(c("source", "recordedplot"), c(1, 3))) - ev <- evaluate(file("plot-multi-layout2.R")) + ev <- evaluate_(" + layout(matrix(c(1, 2, 1, 3, 4, 4), 3, 2, byrow = TRUE)) + # another expression before drawing the plots + x <- 1 + 1 + for (j in 1:2) { + plot(rnorm(10)) + plot(rnorm(10)) + plot(rnorm(10)) + plot(rnorm(10)) + } + ") expect_equal(classes(ev), rep(c("source", "recordedplot"), c(4, 2))) }) test_that("changes in parameters don't generate new plots", { - ev <- evaluate(file("plot-par.R")) + ev <- evaluate_(" + plot(1) + par(mar = rep(0, 4)) + plot(2) + ") expect_equal( classes(ev), c("source", "recordedplot", "source", "source", "recordedplot") @@ -88,27 +146,56 @@ test_that("changes in parameters don't generate new plots", { }) test_that("plots in a loop are captured even the changes seem to be from par only", { - ev <- evaluate(file("plot-par2.R")) + ev <- evaluate_(' + barplot(table(mtcars$mpg), main = "All") + # should capture all plots in this loop + for (numcyl in levels(as.factor(mtcars$cyl))) { + barplot(table(mtcars$mpg[mtcars$cyl == numcyl]), main = paste("cyl = ", numcyl)) + } + ') expect_equal(classes(ev), c("source", "recordedplot")[c(1, 2, 1, 1, 2, 2, 2)]) }) test_that("strwidth()/strheight() should not produce new plots", { - ev <- evaluate(file("plot-strwidth.R")) + ev <- evaluate_(" + x <- strwidth('foo', 'inches') + y <- strheight('foo', 'inches') + par(mar = c(4, 4, 1, 1)) + plot(1) + ") expect_equal(classes(ev), rep(c("source", "recordedplot"), c(4, 1))) }) test_that("clip() does not produce new plots", { - ev <- evaluate(file("plot-clip.R")) + ev <- evaluate_(" + plot(rnorm(100), rnorm(100)) + clip(-1, 1, -1, 1) + points(rnorm(100), rnorm(100), col = 'red') + ") expect_equal(classes(ev), c("source", "recordedplot")[c(1, 2, 1, 1, 2)]) }) test_that("perspective plots are captured", { - ev <- evaluate(file("plot-persp.R")) + ev <- evaluate_(" + x <- seq(-10, 10, length = 30) + y <- x + ff <- function(x,y) { r <- sqrt(x^2 + y^2); 10 * sin(r) / r } + z <- outer(x, y, ff) + z[is.na(z)] <- 1 + for (i in 1:3) { + persp(x, y, z, phi = 30 + i * 10, theta = 30) + } + ") expect_equal(classes(ev), rep(c("source", "recordedplot"), c(6, 3))) }) test_that("an incomplete plot with a comment in the end is also captured", { - ev <- evaluate(file("plot-last-comment.R")) + ev <- evaluate_(" + par(mfrow = c(3, 3)) + for (i in 1:7) + image(volcano) + # comment + ") expect_equal(classes(ev), rep(c("source", "recordedplot"), c(3, 1))) }) @@ -120,7 +207,7 @@ test_that("repeatedly drawing the same plot does not omit plots randomly", { # test_that("no plot windows open", { # graphics.off() # expect_equal(length(dev.list()), 0) -# evaluate(file("plot.R")) +# evaluate("plot(1)") # expect_equal(length(dev.list()), 0) # }) @@ -134,7 +221,7 @@ test_that("by default, evaluate() always records plots regardless of the device" test_that("Rplots.pdf files are not created", { op <- options(device = pdf) on.exit(options(op)) - evaluate(file("plot.R")) + evaluate("plot(1)") expect_false(file.exists("Rplots.pdf")) }) diff --git a/tests/testthat/test-output.R b/tests/testthat/test-output.R index a7bc251b..ffe52daa 100644 --- a/tests/testthat/test-output.R +++ b/tests/testthat/test-output.R @@ -1,6 +1,6 @@ test_that("open plot windows maintained", { n <- length(dev.list()) - evaluate(file("plot.R")) + evaluate("plot(1)") expect_length(dev.list(), n) }) diff --git a/tests/testthat/try.R b/tests/testthat/try.R deleted file mode 100644 index 5ae5daa8..00000000 --- a/tests/testthat/try.R +++ /dev/null @@ -1,4 +0,0 @@ -g <- function() f("error") -f <- function(x) stop(paste0("Obscure ", x)) - -try(g()) From 5a0ff65f7de0b24d64dc535df7931f0eaf960c62 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 18 Jun 2024 16:05:59 +0100 Subject: [PATCH 2/4] Inline replay examples --- DESCRIPTION | 2 +- R/replay.R | 20 +++++++++++++++----- man/replay.Rd | 20 +++++++++++++++----- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index dbb1b24b..fb36680a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -37,4 +37,4 @@ Config/Needs/website: tidyverse/tidytemplate Config/testthat/edition: 3 Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.1 diff --git a/R/replay.R b/R/replay.R index d0b16c2e..3175a91c 100644 --- a/R/replay.R +++ b/R/replay.R @@ -6,12 +6,22 @@ #' @param x result from [evaluate()] #' @export #' @examples -#' samples <- system.file("tests", "testthat", package = "evaluate") -#' if (file_test("-d", samples)) { -#' replay(evaluate(file(file.path(samples, "order.R")))) -#' replay(evaluate(file(file.path(samples, "plot.R")))) -#' replay(evaluate(file(file.path(samples, "data.R")))) +#' f1 <- function() { +#' cat("1\n") +#' print("2") +#' warning("3") +#' print("4") +#' message("5") +#' stop("6") #' } +#' replay(evaluate("f1()")) +#' +#' f2 <- function() { +#' message("Hello") +#' plot(1:10) +#' message("Goodbye") +#' } +#' replay(evaluate("f2()")) replay <- function(x) UseMethod("replay", x) #' @export diff --git a/man/replay.Rd b/man/replay.Rd index b9f18b21..4ddbdf01 100644 --- a/man/replay.Rd +++ b/man/replay.Rd @@ -14,10 +14,20 @@ Replay a list of evaluated results, as if you'd run them in an R terminal. } \examples{ -samples <- system.file("tests", "testthat", package = "evaluate") -if (file_test("-d", samples)) { - replay(evaluate(file(file.path(samples, "order.R")))) - replay(evaluate(file(file.path(samples, "plot.R")))) - replay(evaluate(file(file.path(samples, "data.R")))) +f1 <- function() { + cat("1\n") + print("2") + warning("3") + print("4") + message("5") + stop("6") } +replay(evaluate("f1()")) + +f2 <- function() { + message("Hello") + plot(1:10) + message("Goodbye") +} +replay(evaluate("f2()")) } From a05783f180dbd8c675098a95ac03f66544d856fe Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 18 Jun 2024 16:07:23 +0100 Subject: [PATCH 3/4] WS --- tests/testthat/test-errors.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test-errors.R b/tests/testthat/test-errors.R index 9dd6510d..39bc2e0f 100644 --- a/tests/testthat/test-errors.R +++ b/tests/testthat/test-errors.R @@ -32,8 +32,8 @@ test_that("traceback useful if stop_on_error == 2L", { }) test_that("capture messages in try() (#88)", { - # TODO: figure out why this doesn't work interactively - ev <- evaluate_(' + # TODO: figure out why this doesn't work interactively + ev <- evaluate_(' g <- function() f("error") f <- function(x) stop(paste0("Obscure ", x)) From be16ef71b3eba62545e7da35c60568f29cbb1262 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 18 Jun 2024 16:10:41 +0100 Subject: [PATCH 4/4] Remove TODOs --- tests/testthat/test-errors.R | 1 - tests/testthat/test-graphics.R | 13 ++++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/tests/testthat/test-errors.R b/tests/testthat/test-errors.R index 39bc2e0f..163044ea 100644 --- a/tests/testthat/test-errors.R +++ b/tests/testthat/test-errors.R @@ -32,7 +32,6 @@ test_that("traceback useful if stop_on_error == 2L", { }) test_that("capture messages in try() (#88)", { - # TODO: figure out why this doesn't work interactively ev <- evaluate_(' g <- function() f("error") f <- function(x) stop(paste0("Obscure ", x)) diff --git a/tests/testthat/test-graphics.R b/tests/testthat/test-graphics.R index dc60ad08..014f4eb0 100644 --- a/tests/testthat/test-graphics.R +++ b/tests/testthat/test-graphics.R @@ -5,16 +5,11 @@ test_that("single plot is captured", { }) test_that("ggplot is captured", { - # TODO: figure out why this doesn't work interactively: probably because - # the root environment is wrong - needs to be parent of global env skip_if_not_installed("ggplot2") - - ev <- evaluate_(" - suppressPackageStartupMessages(library(ggplot2)) - ggplot(mtcars, aes(mpg, wt)) + geom_point() - ") - expect_length(ev, 3) - expect_equal(classes(ev), c("source", "source", "recordedplot")) + ev <- evaluate( + "ggplot2::ggplot(mtcars, ggplot2::aes(mpg, wt)) + ggplot2::geom_point()" + ) + expect_equal(classes(ev), c("source", "recordedplot")) }) test_that("plot additions are captured", {