Nothing
library(testthat)
library(rms)
## ---- CORE INPUT CHECKS ----
# Test that ggrmsMD errors if a non-rms object is supplied
test_that("Error if non-rms object is supplied", {
data <- simulated_rmsMD_data()
lmfit <- lm(lengthstay ~ age + bmi, data = data)
expect_error(
ggrmsMD(lmfit, data),
"modelfit is not from an rms model"
)
})
# Test that ggrmsMD errors if there are no RCS variables in the model
test_that("Error if no RCS variables in model", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ age + bmi, data = data)
expect_error(
ggrmsMD(fit, data),
"No variables specified, and no RCS variables in model"
)
})
# Test error if variable in `var` argument is not numeric
test_that("Error if var specified is not numeric", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 4) + rcs(bmi, 4), data = data)
expect_error(
suppressWarnings(
ggrmsMD(fit, data, var = "sex")
),
"All variables being plotted must be numeric."
)
})
# Test warning if variable in `var` argument is not modelled as RCS
test_that("Warning if var specified is not in model as RCS", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 4), data = data)
expect_warning(
try(ggrmsMD(fit, data, var = "bmi"), silent = TRUE),
"Some selected variables were not modelled as RCS"
)
})
## ---- BASIC OUTPUT TYPES ----
# Test that ggrmsMD returns a ggplot object for a single RCS variable
test_that("Returns ggplot for a single RCS variable (OLS)", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 4), data = data)
p <- ggrmsMD(fit, data)
expect_s3_class(p, "ggplot")
})
# Test that ggrmsMD returns a list of ggplots for multiple RCS variables
test_that("Returns list of ggplots for multiple RCS variables", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 4) + rcs(bmi, 4), data = data)
plots <- ggrmsMD(fit, data, combined = FALSE)
expect_type(plots, "list")
expect_s3_class(plots[[1]], "ggplot")
expect_equal(length(plots), 2)
})
# Test that ggrmsMD returns cowplot::plot_grid when combined = TRUE
test_that("Returns cowplot::plot_grid when combined = TRUE", {
skip_if_not_installed("cowplot")
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 4) + rcs(bmi, 4), data = data)
combined_plot <- ggrmsMD(fit, data, combined = TRUE)
expect_true(any(class(combined_plot) %in% c("gg", "gtable")))
})
## ---- DIFFERENT MODEL TYPES ----
# Test that ggrmsMD works for lrm (logistic regression) models (OR)
test_that("Works for lrm models (odds ratio)", {
data <- simulated_rmsMD_data()
data$bin_outcome <- as.factor(data$lengthstay > median(data$lengthstay))
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::lrm(bin_outcome ~ rcs(age, 4), data = data)
p <- ggrmsMD(fit, data)
expect_s3_class(p, "ggplot")
})
# Test that ggrmsMD works for lrm models with lrm_prob = TRUE (predicted probability)
test_that("Works for lrm models (predicted probability)", {
data <- simulated_rmsMD_data()
data$bin_outcome <- as.factor(data$lengthstay > median(data$lengthstay))
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::lrm(bin_outcome ~ rcs(age, 4), data = data)
p <- ggrmsMD(fit, data, lrm_prob = TRUE)
expect_s3_class(p, "ggplot")
expect_match(p$labels$y, "Predicted probability")
})
# Test that ggrmsMD works for cph (Cox) models
test_that("Works for cph models", {
data <- simulated_rmsMD_data()
# Fake a time-to-event outcome just for test (lengthstay as time, majorcomplication as event)
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::cph(Surv(lengthstay, majorcomplication) ~ rcs(age, 4), data = data, x = TRUE, y = TRUE)
p <- ggrmsMD(fit, data)
expect_s3_class(p, "ggplot")
})
## ---- ARGUMENT/FEATURE TESTS ----
# Test custom axis labels and titles
test_that("Custom x/y labels and plot titles work", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 4), data = data)
xlabs <- list(age = "Patient Age (years)")
titles <- list(age = "Spline of Age")
p <- ggrmsMD(fit, data, xlabs = xlabs, ylab = "Custom Y", titles = titles)
expect_identical(p$labels$x, "Patient Age (years)")
expect_identical(p$labels$y, "Custom Y")
expect_identical(p$labels$title, "Spline of Age")
})
# Test custom limits and scaling
test_that("Custom y-axis and x-axis limits work", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 4), data = data)
p <- ggrmsMD(fit, data, ylim = c(0, 50), xlims = list(age = c(20, 80)))
# Test y-axis limits set in the coordinates
expect_equal(p$coordinates$limits$y, c(0, 50))
# Optionally, also test x-axis limits
expect_equal(p$coordinates$limits$x, c(20, 80))
})
# Test log y and log x axes
test_that("log_y and log_x_vars options work without error", {
data <- simulated_rmsMD_data()
data$logage <- data$age + 25 # ensure >0
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(logage, 4), data = data)
expect_s3_class(
ggrmsMD(fit, data, log_y = TRUE, log_x_vars = "logage"),
"ggplot"
)
})
# Test shade_inferior argument
test_that("shade_inferior works for 'higher' and 'lower'", {
data <- simulated_rmsMD_data()
data$bin_outcome <- as.factor(data$lengthstay > median(data$lengthstay))
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::lrm(bin_outcome ~ rcs(age, 4), data = data)
expect_s3_class(
ggrmsMD(fit, data, shade_inferior = "higher"),
"ggplot"
)
expect_s3_class(
ggrmsMD(fit, data, shade_inferior = "lower"),
"ggplot"
)
})
# Test omitting the no-effect line
test_that("noeffline = FALSE omits the dashed line", {
data <- simulated_rmsMD_data()
data$bin_outcome <- as.factor(data$lengthstay > median(data$lengthstay))
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::lrm(bin_outcome ~ rcs(age, 4), data = data)
p <- ggrmsMD(fit, data, noeffline = FALSE)
# Just check it returns a plot, visual checks can be added if needed
expect_s3_class(p, "ggplot")
})
# Test custom number of prediction points
test_that("np argument works for prediction points", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 6), data = data)
p_10 <- ggrmsMD(fit, data, np = 10)
expect_s3_class(p_10, "ggplot")
})
## ---- EDGE/ROBUSTNESS TESTS ----
# Test using only a subset of RCS variables via var
test_that("Subset of RCS variables via var works", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 4) + rcs(bmi, 4), data = data)
# Ask for just one RCS variable (e.g. "age")
plot <- ggrmsMD(fit, data, var = "age", combined = FALSE)
# Should return a single ggplot object, not a list
expect_s3_class(plot, "ggplot")
# If you request both, should return a list of two ggplots
plotlist <- ggrmsMD(fit, data, var = c("age", "bmi"), combined = FALSE)
expect_true(is.list(plotlist))
expect_equal(length(plotlist), 2)
expect_s3_class(plotlist[[1]], "ggplot")
expect_s3_class(plotlist[[2]], "ggplot")
})
# Test that missing data does not cause unexpected crash
test_that("Function handles missing data gracefully", {
data <- simulated_rmsMD_data()
data$age[1:10] <- NA
dd <- datadist(na.omit(data))
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit <- rms::ols(lengthstay ~ rcs(age, 4), data = na.omit(data))
p <- ggrmsMD(fit, na.omit(data))
expect_s3_class(p, "ggplot")
})
# Test repeated calls without resetting datadist
test_that("Multiple calls to ggrmsMD work without resetting datadist", {
data <- simulated_rmsMD_data()
dd <- datadist(data)
assign("dd", dd, envir = .GlobalEnv)
options(datadist = "dd")
fit1 <- rms::ols(lengthstay ~ rcs(age, 4), data = data)
fit2 <- rms::ols(lengthstay ~ rcs(bmi, 4), data = data)
p1 <- ggrmsMD(fit1, data)
p2 <- ggrmsMD(fit2, data)
expect_s3_class(p1, "ggplot")
expect_s3_class(p2, "ggplot")
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.