|
1 | | -#' Try evaluating an expressing multiple times until it succeeds. |
| 1 | +#' Try evaluating an expressing multiple times until it succeeds |
2 | 2 | #' |
3 | | -#' @param times Maximum number of attempts. |
4 | | -#' @param code Code to evaluate |
5 | | -#' @keywords internal |
| 3 | +#' If you have a flaky test, you can use `try_again()` to run it a few times |
| 4 | +#' until it succeeds. In most cases, you are better fixing the underlying |
| 5 | +#' cause of the flakeyness, but sometimes that's not possible. |
| 6 | +#' |
| 7 | +#' @param times Number of times to retry. |
| 8 | +#' @param code Code to evaluate. |
6 | 9 | #' @export |
7 | 10 | #' @examples |
8 | | -#' third_try <- local({ |
9 | | -#' i <- 3 |
10 | | -#' function() { |
11 | | -#' i <<- i - 1 |
12 | | -#' if (i > 0) fail(paste0("i is ", i)) |
13 | | -#' } |
14 | | -#' }) |
15 | | -#' try_again(3, third_try()) |
| 11 | +#' usually_return_1 <- function(i) { |
| 12 | +#' if (runif(1) < 0.1) 0 else 1 |
| 13 | +#' } |
| 14 | +#' |
| 15 | +#' \dontrun{ |
| 16 | +#' # 10% chance of failure: |
| 17 | +#' expect_equal(usually_return_1(), 1) |
| 18 | +#' |
| 19 | +#' # 1% chance of failure: |
| 20 | +#' try_again(3, expect_equal(usually_return_1(), 1)) |
| 21 | +#' } |
16 | 22 | try_again <- function(times, code) { |
17 | | - while (times > 0) { |
18 | | - e <- tryCatch( |
19 | | - withCallingHandlers( |
20 | | - { |
21 | | - code |
22 | | - NULL |
23 | | - }, |
24 | | - warning = function(e) { |
25 | | - if ( |
26 | | - identical(e$message, "restarting interrupted promise evaluation") |
27 | | - ) { |
28 | | - tryInvokeRestart("muffleWarning") |
29 | | - } |
30 | | - } |
31 | | - ), |
32 | | - expectation_failure = function(e) { |
33 | | - e |
34 | | - }, |
35 | | - error = function(e) { |
36 | | - e |
37 | | - } |
38 | | - ) |
| 23 | + check_number_whole(times, min = 1) |
39 | 24 |
|
40 | | - if (is.null(e)) { |
41 | | - return(invisible(TRUE)) |
42 | | - } |
| 25 | + code <- enquo(code) |
43 | 26 |
|
44 | | - times <- times - 1L |
| 27 | + i <- 1 |
| 28 | + while (i <= times) { |
| 29 | + tryCatch( |
| 30 | + return(eval(get_expr(code), get_env(code))), |
| 31 | + expectation_failure = function(cnd) NULL |
| 32 | + ) |
| 33 | + cli::cli_inform(c(i = "Expectation failed; trying again ({i})...")) |
| 34 | + i <- i + 1 |
45 | 35 | } |
46 | 36 |
|
47 | | - exp_signal(e) |
| 37 | + eval(get_expr(code), get_env(code)) |
48 | 38 | } |
0 commit comments