diff --git a/R/GradingResults.R b/R/GradingResults.R index cf5d4f2..f870ab7 100644 --- a/R/GradingResults.R +++ b/R/GradingResults.R @@ -46,7 +46,7 @@ GradingResults <- R6::R6Class( #' #' @return The JSON string to_json = function() { - return(jsonlite::toJSON(self$to_list(), auto_unbox = TRUE, pretty = TRUE)) + return(jsonlite::toJSON(self$to_list(), auto_unbox = TRUE, pretty = TRUE, null = "null")) } ) ) diff --git a/R/TestFileResult.R b/R/TestFileResult.R index b1cd78f..640122f 100644 --- a/R/TestFileResult.R +++ b/R/TestFileResult.R @@ -4,19 +4,23 @@ #' #' @field test_case_results The [TestCaseResult] objects that make up this test file #' @field filename The name of the test file +#' @field points The point value of the test file or a list of test case point values TestFileResult <- R6::R6Class( "TestFileResult", public = list( test_case_results = NA, filename = NA, + points = NA, #' @description Create a test file result. #' #' @param filename The name of the test file #' @param test_case_results The [TestCaseResult] objects that make up this test file - initialize = function(filename, test_case_results) { + #' @param points The point value of the test file or a list of test case point values + initialize = function(filename, test_case_results, points = NULL) { self$filename <- filename self$test_case_results <- test_case_results + self$points <- points }, #' @description Get the basename of the file this result corresponds to. @@ -78,10 +82,16 @@ TestFileResult <- R6::R6Class( tcr_lists[[i]] = self$test_case_results[[i]]$to_list() } - return(list( + ret <- list( filename = self$filename, test_case_results = tcr_lists - )) + ) + + if (!nullish(self$points)) { + ret$points <- self$points + } + + return(ret) } ) ) diff --git a/R/check.R b/R/check.R index 3bb8793..7c634ca 100644 --- a/R/check.R +++ b/R/check.R @@ -32,12 +32,14 @@ check <- function(test_file, test_env, show_results) { eval("options(testthat.use_colours = FALSE)", test_env) + test_suite <- list() test_case_results <- c() # redirect stdout so that testthat doesn't print testthat::capture_output({ # read the test cases from the test file - test_cases <- load_test_cases(test_file)$cases + test_suite <- load_test_cases(test_file) + test_cases <- test_suite$cases # run the tests for (tc in test_cases) { @@ -46,7 +48,7 @@ check <- function(test_file, test_env, show_results) { } }) - file_result <- TestFileResult$new(test_file, test_case_results) + file_result <- TestFileResult$new(test_file, test_case_results, test_suite$points) # collect the result if needed if (!is.null(get_collector())) { diff --git a/R/utils.R b/R/utils.R index 60c6fc5..49ba254 100644 --- a/R/utils.R +++ b/R/utils.R @@ -58,3 +58,12 @@ valid_syntax <- function(script) { ) return(!error) } + +#' Check whether a value is nullish (i.e. NULL or NA) +#' +#' @param x The value to cehck +#' +#' @return Whether the value is nullish +nullish <- function(x) { + return(is.null(x) || is.na(x)) +} diff --git a/man/TestFileResult.Rd b/man/TestFileResult.Rd index d73c5e1..b64cf95 100644 --- a/man/TestFileResult.Rd +++ b/man/TestFileResult.Rd @@ -12,6 +12,8 @@ A collection of test case results that correspond to a single test file. \item{\code{test_case_results}}{The \link{TestCaseResult} objects that make up this test file} \item{\code{filename}}{The name of the test file} + +\item{\code{points}}{The point value of the test file or a list of test case point values} } \if{html}{\out{}} } @@ -32,7 +34,7 @@ A collection of test case results that correspond to a single test file. \subsection{Method \code{new()}}{ Create a test file result. \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TestFileResult$new(filename, test_case_results)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{TestFileResult$new(filename, test_case_results, points = NULL)}\if{html}{\out{
}} } \subsection{Arguments}{ @@ -41,6 +43,8 @@ Create a test file result. \item{\code{filename}}{The name of the test file} \item{\code{test_case_results}}{The \link{TestCaseResult} objects that make up this test file} + +\item{\code{points}}{The point value of the test file or a list of test case point values} } \if{html}{\out{}} } diff --git a/man/export.Rd b/man/export.Rd index a113683..361a09e 100644 --- a/man/export.Rd +++ b/man/export.Rd @@ -2,12 +2,12 @@ % Please edit documentation in R/export.R \name{export} \alias{export} -\title{Export a JupyterNotebook to a zip file} +\title{Export a submission to a zip file} \usage{ export(submission_path, export_path = NULL, display_link = TRUE, pdf = FALSE) } \arguments{ -\item{submission_path}{The path to the notebook} +\item{submission_path}{The path to the submission} \item{export_path}{The path at which to write the zip file (optional)} @@ -16,7 +16,7 @@ export(submission_path, export_path = NULL, display_link = TRUE, pdf = FALSE) \item{pdf}{Whether to include a PDF of the submission (only works for Rmd and ipynb files)} } \description{ -Export a Jupyter Notebook to a zip file for submission. If indicated, a PDF of the +Export a submission to a zip file for submitting. If indicated, a PDF of the submission is generated and included in the zip file. (PDF generation is only supported for Rmd and ipynb files.) } diff --git a/man/nullish.Rd b/man/nullish.Rd new file mode 100644 index 0000000..8d8d69d --- /dev/null +++ b/man/nullish.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{nullish} +\alias{nullish} +\title{Check whether a value is nullish (i.e. NULL or NA)} +\usage{ +nullish(x) +} +\arguments{ +\item{x}{The value to cehck} +} +\value{ +Whether the value is nullish +} +\description{ +Check whether a value is nullish (i.e. NULL or NA) +} diff --git a/tests/testthat/test_GradingResults.R b/tests/testthat/test_GradingResults.R index bb03132..90b645c 100644 --- a/tests/testthat/test_GradingResults.R +++ b/tests/testthat/test_GradingResults.R @@ -21,6 +21,6 @@ test_that("$to_json() returns the grading results as JSON", { expect_equal( gr$to_json(), - jsonlite::toJSON(make_test_file_results_list(), auto_unbox = TRUE, pretty = TRUE) + jsonlite::toJSON(make_test_file_results_list(), auto_unbox = TRUE, pretty = TRUE, null = "null") ) }) diff --git a/tests/testthat/test_TestFileResult.R b/tests/testthat/test_TestFileResult.R index 1b57c0b..0d6f02c 100644 --- a/tests/testthat/test_TestFileResult.R +++ b/tests/testthat/test_TestFileResult.R @@ -17,6 +17,12 @@ test_that("$new() initializes fields correctly", { expect_equal(tfr$filename, filename) expect_equal(tfr$test_case_results, tcrs) + + tfr <- TestFileResult$new(filename, tcrs, 2) + + expect_equal(tfr$filename, filename) + expect_equal(tfr$test_case_results, tcrs) + expect_equal(tfr$points, 2) }) test_that("$get_basename() returns the basename of the test file", { @@ -79,4 +85,22 @@ test_that("$to_list() returns the test file results as a list", { expect_equal(length(tfr_list), 2) expect_equal(tfr_list$filename, filename) expect_equal(tfr_list$test_case_results, lapply(tcrs, function(tcr) tcr$to_list())) + + tfr <- TestFileResult$new(filename, tcrs, 2) + tfr_list <- tfr$to_list() + + expect_true(is.list(tfr_list)) + expect_equal(length(tfr_list), 3) + expect_equal(tfr_list$filename, filename) + expect_equal(tfr_list$test_case_results, lapply(tcrs, function(tcr) tcr$to_list())) + expect_equal(tfr_list$points, 2) + + tfr <- TestFileResult$new(filename, tcrs, c(1, 1, 1)) + tfr_list <- tfr$to_list() + + expect_true(is.list(tfr_list)) + expect_equal(length(tfr_list), 3) + expect_equal(tfr_list$filename, filename) + expect_equal(tfr_list$test_case_results, lapply(tcrs, function(tcr) tcr$to_list())) + expect_equal(tfr_list$points, c(1, 1, 1)) }) diff --git a/tests/testthat/test_check.R b/tests/testthat/test_check.R index eef5288..c4977b8 100644 --- a/tests/testthat/test_check.R +++ b/tests/testthat/test_check.R @@ -33,3 +33,24 @@ test_that("runs a test against the student's environment and returns a TestFileR # check that it errors if no test file is provided expect_error(check(), regexp = "must have a test file") }) + + +test_that("correctly includes the test file point value in the TestFileR", { + test_env <- new.env() + mock_parent.frame <- mock(test_env, cycle = TRUE) + stub(check, "parent.frame", mock_parent.frame) + + mock_cat <- mock() + stub(check, "cat", mock_cat) + + mock_load_test_cases <- mock(list( + cases = list(ottr::TestCase$new(name = "q1")), + points = 1 + ), cycle = TRUE) + stub(check, "load_test_cases", mock_load_test_cases) + test_file_path <- "tests/q1.r" + + results <- check(test_file_path) + + expect_equal(results$points, 1) +})