Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move error checking from render_exercise() to evaluate_exercise() #544

Merged
merged 25 commits into from
Jul 9, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4503f76
Move exercise error checking code into `evaluate_exercise()` from `re…
rossellhayes Jun 22, 2021
259a082
Remove breadcrumbs
rossellhayes Jun 22, 2021
ca144c9
Use more specific error class for render errors
rossellhayes Jun 24, 2021
c3c38ae
Simplify test
rossellhayes Jun 24, 2021
aa6abd7
Use `rlang::catch_cnd()` instead of `tryCatch()`
rossellhayes Jun 24, 2021
0cb3dfd
Run code checks before creating temp dir
rossellhayes Jun 24, 2021
bcd5dc3
Use `local_dir()` instead of `with_dir()` in `evaluate_exercise()`
rossellhayes Jun 24, 2021
18b0fa0
Simplify creation of tempdir
rossellhayes Jun 24, 2021
6e19e4a
Modify test to check `render_exercise()` and `evaluate_exercise()`
rossellhayes Jun 24, 2021
f04bdd4
Fix bug in returning error message
rossellhayes Jun 25, 2021
ea1675b
Update tests of `render_exercise()` and transfer tests to `evaluate_e…
rossellhayes Jun 25, 2021
14d058e
Fix merge conflicts
rossellhayes Jul 9, 2021
939eda6
Build docs (GitHub Actions)
rossellhayes Jul 9, 2021
c0ba8a1
Restore data directory feature
gadenbuie Jul 9, 2021
f56e82e
Fix merge conflict
rossellhayes Jul 9, 2021
cd6e8f7
Fix merge conflict
rossellhayes Jul 9, 2021
c0149cf
Restore withr::local_tempdir()
gadenbuie Jul 9, 2021
3365c8e
Fix comment about purpose of render_exercise()
gadenbuie Jul 9, 2021
c5e8a89
Rename error object in render_exercise error
gadenbuie Jul 9, 2021
ee19db2
Add test for exercises that exceed the timelimt
gadenbuie Jul 9, 2021
9dab33f
More specific tests for presence of error_check code
gadenbuie Jul 9, 2021
bd095ba
Standardize exercise checking-related code to length-1 string
gadenbuie Jul 9, 2021
a4030f0
Skip timelimit test on windows
gadenbuie Jul 9, 2021
be678f4
Factor out `standardize_code()`
gadenbuie Jul 9, 2021
287aca3
Add NEWS item
gadenbuie Jul 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 30 additions & 17 deletions R/exercise.R
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,28 @@ evaluate_exercise <- function(exercise, envir, evaluate_global_setup = FALSE) {
# Resolve knitr options for the exercise and setup chunks
rmd_results <- withr::with_dir(
exercise_dir,
render_exercise(exercise, envir)
tryCatch(
render_exercise(exercise, envir),
error = function(e) {
if (length(exercise$error_check)) {
# Run the condition through an error checker
# (the exercise could be to throw an error!)
checker_feedback <- try_checker(
exercise, "exercise.checker",
check_code = exercise$error_check,
envir_result = e$envir_result,
evaluate_result = e$evaluate_result,
envir_prep = e$envir_prep,
last_value = e$e,
engine = exercise$engine
)
if (is_exercise_result(checker_feedback)) {
return(checker_feedback)
}
}
exercise_result_error(e$msg)
}
)
)

if (is_exercise_result(rmd_results)) {
Expand Down Expand Up @@ -548,22 +569,14 @@ render_exercise <- function(exercise, envir) {
if (grepl(pattern, msg, fixed = TRUE)) {
return(exercise_result_timeout())
}
if (length(exercise$error_check)) {
# Run the condition through an error checker (the exercise could be to throw an error!)
checker_feedback <- try_checker(
exercise, "exercise.checker",
check_code = exercise$error_check,
envir_result = envir_result,
evaluate_result = evaluate_result,
envir_prep = envir_prep,
last_value = e,
engine = exercise$engine
)
if (is_exercise_result(checker_feedback)) {
return(checker_feedback)
}
}
exercise_result_error(msg)
rlang::abort(
class = "learnr_exercise_result",
rossellhayes marked this conversation as resolved.
Show resolved Hide resolved
envir_result = envir_result,
evaluate_result = evaluate_result,
envir_prep = envir_prep,
last_value = e,
error_message = msg
)
})

if (is_exercise_result(output_file)) {
Expand Down
38 changes: 24 additions & 14 deletions tests/testthat/test-exercise.R
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,9 @@ test_that("render_exercise() returns identical envir_prep and envir_result if an
error_check = "unevaluated, triggers error_check in render_exercise()"
)

exercise_result <- withr::with_tempdir(render_exercise(exercise, new.env()))

# the error during render causes a checker evaluation, so we can recover
# the environments from the checker_args returned by the debug checker
exercise_result <- exercise_result$feedback$checker_args
exercise_result <- withr::with_tempdir(
tryCatch(render_exercise(exercise, new.env()), error = identity)
)

expect_s3_class(exercise_result$last_value, "simpleError")
expect_equal(conditionMessage(exercise_result$last_value), "boom")
Expand All @@ -162,11 +160,9 @@ test_that("render_exercise() returns envir_result up to error", {
error_check = "unevaluated, triggers error_check in render_exercise()"
)

exercise_result <- withr::with_tempdir(render_exercise(exercise, new.env()))

# the error during render causes a checker evaluation, so we can recover
# the environments from the checker_args returned by the debug checker
exercise_result <- exercise_result$feedback$checker_args
exercise_result <- withr::with_tempdir(
tryCatch(render_exercise(exercise, new.env()), error = identity)
)

expect_s3_class(exercise_result$last_value, "simpleError")
expect_equal(conditionMessage(exercise_result$last_value), "boom")
Expand All @@ -184,13 +180,17 @@ test_that("render_exercise() with errors and no checker returns exercise result
setup_label = "setup-1"
)

exercise_result <- withr::with_tempdir(render_exercise(exercise, new.env()))
exercise_result <- withr::with_tempdir(
tryCatch(render_exercise(exercise, new.env()), error = identity)
)
expect_s3_class(exercise_result, "learnr_exercise_result")
expect_identical(exercise_result$error_message, "setup")
expect_null(exercise_result$feedback)

exercise <- mock_exercise(user_code = "stop('user')")
exercise_result <- withr::with_tempdir(render_exercise(exercise, new.env()))
exercise_result <- withr::with_tempdir(
tryCatch(render_exercise(exercise, new.env()), error = identity)
)
expect_s3_class(exercise_result, "learnr_exercise_result")
expect_identical(exercise_result$error_message, "user")
expect_null(exercise_result$feedback)
Expand Down Expand Up @@ -228,8 +228,18 @@ test_that("render_exercise() cleans up exercise_prep files even when setup fails

files <- expect_message(
withr::with_tempdir({
before <- dir()
res <- render_exercise(exercise, new.env())
before <- dir()
e <- tryCatch(render_exercise(exercise, new.env()), error = identity)
res <- try_checker(
exercise, "exercise.checker",
check_code = exercise$error_check,
envir_result = e$envir_result,
evaluate_result = e$evaluate_result,
envir_prep = e$envir_prep,
last_value = e$e,
engine = exercise$engine
)
rossellhayes marked this conversation as resolved.
Show resolved Hide resolved

list(
before = before,
before_error = get("dir_setup", res$feedback$checker_args$envir_prep),
Expand Down