grade_this() allows instructors to write custom logic to evaluate, grade
and give feedback to students. To use grade_this(), call it directly in
your *-check chunk:
```{r example-check}
grade_this({
  # custom checking code appears here
  if (identical(.result, .solution)) {
    pass("Great work!")
  }
  fail("Try again!")
})
```grade_this() makes available a number of objects based on the exercise and
the student's submission that can be used to evaluate the student's submitted
code. See ?"grade_this-objects" for more information about these objects.
As the instructor, you are free to use any logic to determine a student's
grade as long as a graded() object is signaled. The check code can also
contain testthat expectation code. Failed testthat expectations
will be turned into fail()ed grades with the corresponding message.
A final grade is signaled from grade_this() using the graded() helper
functions, which include pass(), fail(), among others. grade_this()
uses condition handling to short-circuit further evaluation when a grade is
reached. This means that you may also signal a failing grade using any of the
expect_*() functions from testthat, other functions designed to work
with testthat, such as checkmate, or standard R errors via
stop(). Learn more about this behavior in graded() in the section
Return a grade immediately.
Usage
grade_this(
  expr,
  ...,
  maybe_code_feedback = getOption("gradethis.maybe_code_feedback", TRUE)
)Arguments
- expr
- The grade-checking expression to be evaluated. This expression must either signal a grade via - pass()or- fail()functions or their sibling functions.- By default, errors in this expression are converted to "internal problem" grades that mask the error for the user. If your grading logic relies on unit-test-styled functions, such as those from testthat, you can use - fail_if_error()to convert errors into- fail()grades.
- ...
- Ignored 
- maybe_code_feedback
- Should - maybe_code_feedback()provide code feedback when used in a- graded()message? The default value can be set with- gradethis_setup().- Typically, - maybe_code_feedback()is called in the default- fail()message (the default can be customized the- failargument of- gradethis_setup()). If the- maybe_code_feedbackargument is- FALSE,- maybe_code_feedback()returns an empty string.
Value
Returns a function whose first parameter will be an environment
containing objects specific to the exercise and submission (see Available
variables). For local testing, you can create a version of the expected
environment for a mock exercise submission with mock_this_exercise().
Calling the returned function on the exercise-checking environment will
evaluate the grade-checking expr and return a final grade via graded().
Examples
# For an interactive example run: gradethis_demo()
# Suppose we have an exercise that prompts students to calculate the
# average height of Loblolly pine trees using the `Loblolly` data set.
# We might write an exercise `-check` chunk like the one below.
#
# Since grade_this() returns a function, we'll save the result of this
# "chunk" as `grader()`, which can be called on an exercise submission
# to evaluate the student's code, which we'll simulate with
# `mock_this_exercise()`.
grader <-
  # ```{r example-check}
  grade_this({
    if (length(.result) != 1) {
      fail("I expected a single value instead of {length(.result)} values.")
    }
    if (is.na(.result)) {
      fail("I expected a number, but your code returned a missing value.")
    }
    avg_height <- mean(Loblolly$height)
    if (identical(.result, avg_height)) {
      pass("Great work! The average height is {round(avg_height, 2)}.")
    }
    # Always end grade_this() with a default grade.
    # By default fail() will also give code feedback,
    # if a solution is available.
    fail()
  })
# ```
# Simulate an incorrect answer: too many values...
grader(mock_this_exercise(.user_code = Loblolly$height[1:2]))
#> <gradethis_graded: [Incorrect]
#>   I expected a single value instead of 2 values.
#> >
# This student submission returns a missing value...
grader(mock_this_exercise(mean(Loblolly$Seed)))
#> Warning: argument is not numeric or logical: returning NA
#> <gradethis_graded: [Incorrect]
#>   I expected a number, but your code returned a missing value.
#> >
# This student submission isn't caught by any specific tests,
# the final grade is determined by the default (last) value in grade_this()
grader(mock_this_exercise(mean(Loblolly$age)))
#> <gradethis_graded: [Incorrect]
#>   Incorrect. Don't give up now, try it one more time.
#> >
# If you have a *-solution chunk,
# fail() without arguments gives code feedback...
grader(
  mock_this_exercise(
    .user_code = mean(Loblolly$age),
    .solution_code = mean(Loblolly$height)
  )
)
#> <gradethis_graded: [Incorrect]
#>   Incorrect. In `Loblolly$age`, I expected `height` where you
#>   wrote `age`. Let's try it again.
#> >
# Finally, the "student" gets the correct answer!
grader(mock_this_exercise(mean(Loblolly$height)))
#> <gradethis_graded: [Correct]
#>   Great work! The average height is 32.36.
#> >
