If you are looking at the SCTs of old DataCamp courses, you’ll notice they use test_x() functions instead of check_x() functions, and there is no usage of ex(). The test_x() way of doing things has now been phased out in favor of the more verbose, but more transparent and composable check_x() functions that start with ex() and are chained together with the %>% operator.

Common cases

Whenever you come across an SCT that uses test_x() functions, you’ll make everybody’s life easier by converting it to a check_x()-based SCT. Below are the most common cases you will encounter, together with instructions on how to translate from one to the other.

Something you came across that you didn’t find in this list? Just create an issue on testwhat’s GitHub repo. Content Engineering will explain how to translate the SCT and update this article.

test_student_typed()

# Solution
TRUE & FALSE

# old SCT (fixed = TRUE by default)
test_student_typed(c("TRUE & FALSE", "FALSE & TRUE"))

# new SCT (fixed = FALSE by default)
ex() %>% check_code(c("TRUE & FALSE", "FALSE & TRUE"), fixed = TRUE)
# Solution
"Hello, world!"

# equivalent 'old' SCT (fixed = TRUE by default)
test_student_typed("[H|h]ello,*\\s*[W|w]orld\\!*", fixed = FALSE)

# SCT, robust to small typos
ex() %>% check_code("[H|h]ello,*\\s*[W|w]orld\\!*")

test_object()

# Solution
x <- 5

# old SCT
test_object("x")

# new SCT
ex() %>% check_object("x") %>% check_equal()
# Solution, value of x does not matter
x <- 5

# old SCT
test_object("x", eval = FALSE)

# new SCT
ex() %>% check_object("x")

test_function()

# Solution
mean(1:3)

# old SCT
test_function("mean", args = c("x"))

# new SCT
ex() %>% check_function("mean") %>% check_arg("x") %>% check_equal()
# Solution, value of na.rm does not matter
mean(c(1, 2, 3), na.rm = TRUE)

# old SCT
test_function("mean", args = c("x", "na.rm"), eval = c(TRUE, NA))

# SCT
ex() %>% check_function("mean") %>% {
check_arg(., "x") %>% check_equal()
check_arg(., "na.rm")
}

test_error()

# old SCT
test_error()

# new SCT
ex() %>% check_error()

test_function_result()

# Solution
mean(1:3)

# old SCT
test_function_result("mean")

# new SCT
ex() %>% check_function("mean") %>% check_result() %>% check_equal()

test_correct()

# Solution (how x is calculated does not matter)
x <- mean(1:3)

# old SCT
test_correct(test_object("x"), test_function("mean", args = c("x")))

# new SCT
ex() %>% check_correct(
check_object(., "x") %>% check_equal(),
check_fun(., "mean") %>% check_arg("x") %>% check_equal()
)

test_function_definition()

# Solution
my_fun <- function(a, b) {
print("summing")
return(a + b)
}

# old SCT
test_function_definition("my_fun",
function_test = {
test_expression_result("my_fun(1, 2)")
test_expression_output("my_fun(1, 2)")
},
body_test = {
test_function("print", "x")
test_student_typed(c("a + b", "b + a"))
})

# new SCT (not so great)
ex() %>% check_fun_def('my_fun') %>% {
check_arguments(.)
check_call(., 1, 2) %>% {
check_result(.) %>% check_equal()
check_output(.) %>% check_equal()
}
check_body(.) %>% {
check_function(., "print") %>% check_arg("x") %>% check_equal()
check_code(., c("a + b", "b + a"), fixed = TRUE)
}
}

# new SCT (better, uses check_correct)
ex() %>% check_fun_def('my_fun') %>% check_correct(
check_call(., 1, 2) %>% {
check_result(.) %>% check_equal()
check_output(.) %>% check_equal()
},
{
check_arguments(.)
check_body(.) %>% {
check_function(., "print") %>% check_arg("x") %>% check_equal()
check_code(., c("a + b", "b + a"), fixed = TRUE)
}
}
)

Enforcing check functions

For newer courses an updated version of the base Docker image is used that sets the TESTWHAT_V2_ONLY environment variable. When this variable is set, testwhat will no longer allow SCT authors to use the old test_x() functions. If you are updating the Docker image for courses that have old skool SCTs, this would mean you have to rewrite all the SCTs to their check equivalents to make the build pass. If you want to work around this, thus being able to use test functions even with the latest base image, you can include one of the following snippets of code:

# in requirements.sh (bash code)
echo TESTWHAT_V2_ONLY=0 > .Renviron

# in requirements.r (R code)
write("TESWHAT_V2_ONLY=0", file = ".Renviron")