Skip to content

Commit

Permalink
Added new tests for API. The error detection method has been unified …
Browse files Browse the repository at this point in the history
…across the entire API. Added library::function notation where it was missing. The structure has been changed to reflect changes caused by the implementation of code coverage.
  • Loading branch information
salatak committed Feb 6, 2024
1 parent b8f8b67 commit 8f6feaa
Show file tree
Hide file tree
Showing 5 changed files with 554 additions and 297 deletions.
177 changes: 71 additions & 106 deletions R/api_create_study.R
Original file line number Diff line number Diff line change
@@ -1,139 +1,104 @@
api__minimization_pocock <- function( # nolint: cyclocomp_linter.
identifier, name, method, arms, covariates, p, req, res) {
validation_errors <- vector()

err <- checkmate::check_character(name, min.chars = 1, max.chars = 255)
if (err != TRUE) {
validation_errors <- unbiased:::append_error(
validation_errors, "name", err
)
}
collection <- checkmate::makeAssertCollection()

err <- checkmate::check_character(identifier, min.chars = 1, max.chars = 12)
if (err != TRUE) {
validation_errors <- unbiased:::append_error(
validation_errors,
"identifier",
err
)
}
checkmate::assert(
checkmate::check_character(name, min.chars = 1, max.chars = 255),
.var.name = "name",
add = collection
)

err <- checkmate::check_choice(method, choices = c("range", "var", "sd"))
if (err != TRUE) {
validation_errors <- unbiased:::append_error(
validation_errors,
"method",
err
)
}
checkmate::assert(
checkmate::check_character(identifier, min.chars = 1, max.chars = 12),
.var.name = "identifier",
add = collection
)

checkmate::assert(
checkmate::check_choice(method, choices = c("range", "var", "sd")),

Check warning on line 19 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=19,col=4,[indentation_linter] Hanging indent should be 20 spaces but is 4 spaces.
.var.name = "method",
add = collection)

err <-
checkmate::assert(
checkmate::check_list(
arms,
types = "integerish",
any.missing = FALSE,
min.len = 2,
names = "unique"
)
if (err != TRUE) {
validation_errors <- unbiased:::append_error(
validation_errors,
"arms",
err
)
}
),
.var.name = "arms",
add = collection
)

err <-
checkmate::assert(
checkmate::check_list(
covariates,
types = c("numeric", "list", "character"),
any.missing = FALSE,
min.len = 2,
min.len = 1,
names = "unique"
)
if (err != TRUE) {
validation_errors <-
unbiased:::append_error(validation_errors, "covariates", err)
}
),
.var.name = "covariates3",
add = collection
)

response <- list()
for (c_name in names(covariates)) {
c_content <- covariates[[c_name]]

err <- checkmate::check_list(
c_content,
any.missing = FALSE,
len = 2,
)
if (err != TRUE) {
validation_errors <-
unbiased:::append_error(
validation_errors,
glue::glue("covariates[{c_name}]"),
err
)
}
err <- checkmate::check_names(
names(c_content),
permutation.of = c("weight", "levels"),
)
if (err != TRUE) {
validation_errors <-
unbiased:::append_error(
validation_errors,
glue::glue("covariates[{c_name}]"),
err
)
}
checkmate::assert(
checkmate::check_list(

Check warning on line 52 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=52,col=6,[indentation_linter] Hanging indent should be 22 spaces but is 6 spaces.
c_content,
any.missing = FALSE,
len = 2,
),
.var.name = "covariates1",
add = collection)

checkmate::assert(
checkmate::check_names(

Check warning on line 61 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=61,col=6,[indentation_linter] Hanging indent should be 22 spaces but is 6 spaces.
names(c_content),
permutation.of = c("weight", "levels"),
),
.var.name = "covariates2",
add = collection)

# check covariate weight
err <- checkmate::check_numeric(c_content$weight,
lower = 0,
finite = TRUE,
len = 1,
null.ok = FALSE
)
if (err != TRUE) {
validation_errors <-
unbiased:::append_error(
validation_errors,
glue::glue("covariates[{c_name}][weight]"),
err
)
}

err <- checkmate::check_character(c_content$levels,
min.chars = 1,
min.len = 2,
unique = TRUE
)
if (err != TRUE) {
validation_errors <-
unbiased:::append_error(
validation_errors,
glue::glue("covariates[{c_name}][levels]"),
err
)
}
checkmate::assert(
checkmate::check_numeric(c_content$weight,

Check warning on line 70 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=70,col=6,[indentation_linter] Hanging indent should be 22 spaces but is 6 spaces.
lower = 0,

Check warning on line 71 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=71,col=31,[indentation_linter] Indentation should be 24 spaces but is 31 spaces.
finite = TRUE,
len = 1,
null.ok = FALSE
),

Check warning on line 75 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=75,col=6,[indentation_linter] Hanging indent should be 22 spaces but is 6 spaces.
.var.name = "weight",
add = collection)

checkmate::assert(
checkmate::check_character(c_content$levels,

Check warning on line 80 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=80,col=6,[indentation_linter] Hanging indent should be 22 spaces but is 6 spaces.
min.chars = 1,

Check warning on line 81 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=81,col=33,[indentation_linter] Indentation should be 24 spaces but is 33 spaces.
min.len = 2,
unique = TRUE
),

Check warning on line 84 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=84,col=6,[indentation_linter] Hanging indent should be 22 spaces but is 6 spaces.
.var.name = "levels",
add = collection)
}

# check probability
p <- as.numeric(p)
err <- checkmate::check_numeric(p, lower = 0, upper = 1, len = 1)
if (err != TRUE) {
validation_errors <-
unbiased:::append_error(
validation_errors,
"p",
err
)
}
checkmate::assert(
checkmate::check_numeric(p, lower = 0, upper = 1, len = 1,

Check warning on line 91 in R/api_create_study.R

View workflow job for this annotation

GitHub Actions / lint

file=R/api_create_study.R,line=91,col=4,[indentation_linter] Hanging indent should be 20 spaces but is 4 spaces.
any.missing = FALSE, null.ok = FALSE),
.var.name = "p",
add = collection)


if (length(validation_errors) > 0) {
if (length(collection$getMessages()) > 0) {
res$status <- 400
return(list(
error = "Input validation failed",
validation_errors = validation_errors
error = "There was a problem with the input data to create the study",
validation_errors = collection$getMessages()
))
}

Expand Down Expand Up @@ -167,7 +132,7 @@ api__minimization_pocock <- function( # nolint: cyclocomp_linter.
if (!is.null(r$error)) {
res$status <- 503
return(list(
error = "There was a problem creating the study",
error = "There was a problem saving created study to the database",
details = r$error
))
}
Expand Down
160 changes: 79 additions & 81 deletions R/api_randomize.R
Original file line number Diff line number Diff line change
@@ -1,84 +1,3 @@
api__randomize_patient <- function(study_id, current_state, req, res) {
collection <- checkmate::makeAssertCollection()

db_connection_pool <- get("db_connection_pool")

# Check whether study with study_id exists
checkmate::assert(
checkmate::check_subset(
x = req$args$study_id,
choices = dplyr::tbl(db_connection_pool, "study") |>
dplyr::select("id") |>
dplyr::pull()
),
.var.name = "Study ID",
add = collection
)

# Retrieve study details, especially the ones about randomization
method_randomization <-
dplyr::tbl(db_connection_pool, "study") |>
dplyr::filter(.data$id == study_id) |>
dplyr::select("method") |>
dplyr::pull()

checkmate::assert(
checkmate::check_scalar(method_randomization, null.ok = FALSE),
.var.name = "Randomization method",
add = collection
)

if (length(collection$getMessages()) > 0) {
res$status <- 400
return(list(
error = "Study input validation failed",
validation_errors = collection$getMessages()
))
}

# Dispatch based on randomization method to parse parameters
params <-
switch(method_randomization,
minimisation_pocock = tryCatch(
{
do.call(
parse_pocock_parameters,
list(db_connection_pool, study_id, current_state)
)
},
error = function(e) {
res$status <- 400
res$body <- glue::glue("Error message: {conditionMessage(e)}")
logger::log_error("Error: {err}", err = e)
}
)
)

arm_name <-
switch(method_randomization,
minimisation_pocock = tryCatch(
{
do.call(unbiased:::randomize_minimisation_pocock, params)
},
error = function(e) {
res$status <- 400
res$body <- glue::glue("Error message: {conditionMessage(e)}")
logger::log_error("Error: {err}", err = e)
}
)
)

arm <- dplyr::tbl(db_connection_pool, "arm") |>
dplyr::filter(study_id == !!study_id & .data$name == arm_name) |>
dplyr::select(arm_id = "id", "name", "ratio") |>
dplyr::collect()

unbiased:::save_patient(study_id, arm$arm_id) |>
dplyr::mutate(arm_name = arm$name) |>
dplyr::rename(patient_id = "id") |>
as.list()
}

parse_pocock_parameters <-
function(db_connetion_pool, study_id, current_state) {
parameters <-
Expand Down Expand Up @@ -129,3 +48,82 @@ parse_pocock_parameters <-

return(params)
}

api__randomize_patient <- function(study_id, current_state, req, res) {
collection <- checkmate::makeAssertCollection()

db_connection_pool <- get("db_connection_pool")

# Check whether study with study_id exists
checkmate::assert(
checkmate::check_subset(
x = req$args$study_id,
choices = dplyr::tbl(db_connection_pool, "study") |>
dplyr::select(id) |>
dplyr::pull()
),
.var.name = "study_id",
add = collection
)

# Retrieve study details, especially the ones about randomization
method_randomization <-
dplyr::tbl(db_connection_pool, "study") |>
dplyr::filter(id == study_id) |>
dplyr::select("method") |>
dplyr::pull()

checkmate::assert(
checkmate::check_scalar(method_randomization, null.ok = FALSE),
.var.name = "method_randomization",
add = collection
)

if (length(collection$getMessages()) > 0) {
res$status <- 400
return(list(
error = "There was a problem with the randomization preparation",
validation_errors = collection$getMessages()
))
}

# Dispatch based on randomization method to parse parameters
params <-
switch(
method_randomization,
minimisation_pocock = do.call(
parse_pocock_parameters, list(db_connection_pool, study_id, current_state)
)
)

arm_name <-
switch(
method_randomization,
minimisation_pocock = do.call(
unbiased:::randomize_minimisation_pocock, params
)
)

arm <- dplyr::tbl(db_connection_pool, "arm") |>
dplyr::filter(study_id == !!study_id & .data$name == arm_name) |>
dplyr::select("arm_id" = "id", "name", "ratio") |>
dplyr::collect()

randomized_patient <- unbiased:::save_patient(study_id, arm$arm_id)

if (!is.null(randomized_patient$error)) {
res$status <- 503
return(list(
error = "There was a problem saving randomized patient to the database",
details = randomized_patient$error
))
} else {
randomized_patient <-
randomized_patient |>
dplyr::mutate(arm_name = arm$name) |>
dplyr::rename(patient_id = id) |>
as.list()

return(randomized_patient)
}
}
Loading

0 comments on commit 8f6feaa

Please sign in to comment.