Nothing
# sim_accrual --------------------------------------------------------
test_that("sim_accrual returns correct number of values", {
n <- 100
result <- sim_accrual(n = n, accrual_periods = c(6, 8), accrual_props = c(0.5, 0.5))
expect_equal(length(result), n)
expect_true(is.numeric(result))
})
test_that("sim_accrual returns values within expected range", {
# Test with multiple periods
result <- sim_accrual(n = 1000,
accrual_periods = c(6, 8),
accrual_props = c(0.5, 0.5))
expect_true(all(result >= 0))
expect_true(all(result <= 8))
# Values should be distributed across both periods
period1_count <- sum(result < 6)
period2_count <- sum(result >= 6)
# Allow some flexibility due to randomness, but should be roughly 50/50
expect_true(period1_count > 475)
expect_true(period2_count > 475)
})
test_that("sim_accrual works with single accrual period", {
result <- sim_accrual(n = 100,
accrual_periods = c(10),
accrual_props = c(1))
expect_equal(length(result), 100)
expect_true(all(result >= 0))
expect_true(all(result <= 10))
})
test_that("sim_accrual works with unequal accrual proportions", {
set.seed(123) # For reproducibility
result <- sim_accrual(n = 1000,
accrual_periods = c(5, 10, 15),
accrual_props = c(0.2, 0.3, 0.5))
# Roughly 20% should be in first period
period1_count <- sum(result < 5)
# Roughly 30% should be in second period
period2_count <- sum(result >= 5 & result < 10)
# Roughly 50% should be in third period
period3_count <- sum(result >= 10)
# Allow flexibility due to randomness
expect_true(abs(period1_count/1000 - 0.2) < 0.05)
expect_true(abs(period2_count/1000 - 0.3) < 0.05)
expect_true(abs(period3_count/1000 - 0.5) < 0.05)
})
test_that("sim_accrual handles extreme probability distributions", {
# Test with very skewed probability
result <- sim_accrual(n = 1000,
accrual_periods = c(5, 10, 15),
accrual_props = c(0.01, 0.01, 0.98))
# Most values should be in the third period (if perfect would be 980, there is wiggle room)
expect_true(sum(result >= 10) > 950)
})
test_that("sim_accrual handles uneven inputs", {
expect_error(sim_accrual(n = 1000,
accrual_periods = c(5, 10, 15),
accrual_props = c(0.01, 0.01)),
"`accrual_periods` and `accrual_props` should have equal lengths")
})
# sim_pw_const_haz -------------------------------------------------------
test_that("sim_pw_const_haz returns correct number and type of values", {
n <- 100
hazard_periods <- c(5, 10)
hazard_values <- c(0.1, 0.2, 0.3)
# Run the function
set.seed(123)
result <- sim_pw_const_haz(n = n, hazard_periods = hazard_periods, hazard_values = hazard_values)
# Check results
expect_equal(length(result), n)
expect_true(is.numeric(result))
expect_true(all(result >= 0))
})
test_that("sim_pw_const_haz handles constant hazard case", {
n <- 1000
hazard_value <- 0.1
# Run with single hazard value (constant hazard)
set.seed(123)
result <- sim_pw_const_haz(n = n, hazard_values = hazard_value)
# For exponential distribution with rate 0.1, mean should be approximately 10
expect_gt(mean(result), 9)
expect_lt(mean(result), 11)
})
test_that("sim_pw_const_haz handles piecewise constant hazard", {
n <- 1000
hazard_periods <- c(5)
hazard_values <- c(0.05, 0.8) # Low hazard then high hazard
# Run the function
set.seed(123)
result <- sim_pw_const_haz(n = n, hazard_periods = hazard_periods, hazard_values = hazard_values)
# Count events in different periods
early_events <- sum(result <= 5)
late_events <- sum(result > 5)
# With higher hazard in second period, expect more events per unit time
# Calculate event density (events per unit time)
max_time <- max(result)
early_density <- early_events / 5
late_density <- late_events / (max_time - 5)
# Higher hazard should lead to higher event density
expect_gt(late_density, early_density)
})
test_that("sim_pw_const_haz handles edge cases", {
# Very high hazard (should result in early events)
high_hazard_result <- sim_pw_const_haz(n = 100, hazard_values = 10)
expect_true(mean(high_hazard_result) < 1) # Mean should be less than 1 with hazard=10
# Very low hazard (should result in later events)
low_hazard_result <- sim_pw_const_haz(n = 100, hazard_values = 0.01)
expect_true(mean(low_hazard_result) > 50) # Mean should be greater than 50 with hazard=0.01
})
test_that("sim_pw_const_haz validates inputs", {
# Number of hazard values should match number of periods + 1
expect_error(
sim_pw_const_haz(n = 100, hazard_periods = c(5, 10), hazard_values = c(0.1, 0.2)),
"`hazard_values` should have length equal to one more than the length of `hazard_periods`"
)
# Negative hazard values should error
expect_error(
sim_pw_const_haz(n = 100, hazard_values = -0.1),
"`hazard_values` and `hazard_periods` can only have positive values"
)
})
# sim_weib_ph ----------------------------------------------------
test_that("sim_weib_ph returns correct format", {
# Create a simple survreg Weibull model
set.seed(123)
n <- 50
df <- data.frame(
time = rweibull(n, shape = 1.5, scale = 5),
event = sample(0:1, n, replace = TRUE, prob = c(0.2, 0.8)),
cov1 = rnorm(n),
cov2 = rbinom(n, 1, 0.5)
)
weib_model <- survival::survreg(survival::Surv(time, event) ~ cov1 + cov2, data = df, dist = "weibull")
# Create sample data frame
samp_df <- data.frame(
cov1 = rnorm(10),
cov2 = rbinom(10, 1, 0.5)
)
# Run the function
result <- sim_weib_ph(weibull_ph_mod = weib_model, samp_df = samp_df)
# Check results
expect_length(result, nrow(samp_df))
expect_true(all(result > 0))
expect_type(result, "double")
})
test_that("sim_weib_ph handles conditional effects correctly", {
# Create a simple survreg Weibull model
set.seed(123)
n <- 50
df <- data.frame(
time = rweibull(n, shape = 1.5, scale = 5),
event = sample(0:1, n, replace = TRUE, prob = c(0.2, 0.8)),
cov1 = rnorm(n),
cov2 = rbinom(n, 1, 0.5)
)
weib_model <- survival::survreg(survival::Surv(time, event) ~ cov1 + cov2, data = df, dist = "weibull")
# Create sample data frame
set.seed(456)
samp_df <- data.frame(
cov1 = rnorm(100),
cov2 = rbinom(100, 1, 0.5)
)
# Generate times with no drift/treatment effect
base_times <- sim_weib_ph(weibull_ph_mod = weib_model, samp_df = samp_df)
# Generate times with positive drift (should increase survival time)
pos_times <- sim_weib_ph(
weibull_ph_mod = weib_model,
samp_df = samp_df,
cond_drift = 0.5
)
# Generate times with negative treatment effect (should decrease survival time)
neg_times <- sim_weib_ph(
weibull_ph_mod = weib_model,
samp_df = samp_df,
cond_trt_effect = -0.5
)
# Positive drift should increase survival time (higher median)
expect_gt(median(neg_times), median(base_times))
# Negative treatment effect should decrease survival time
expect_lt(median(pos_times), median(base_times))
})
test_that("sim_weib_ph handles empty data correctly", {
# Create a simple survreg Weibull model
set.seed(123)
n <- 50
df <- data.frame(
time = rweibull(n, shape = 1.5, scale = 5),
event = sample(0:1, n, replace = TRUE, prob = c(0.2, 0.8)),
cov1 = rnorm(n),
cov2 = rbinom(n, 1, 0.5)
)
weib_model <- survival::survreg(survival::Surv(time, event) ~ cov1 + cov2, data = df, dist = "weibull")
# Create empty sample data frame with correct columns
samp_df <- data.frame(
cov1 = numeric(0),
cov2 = numeric(0)
)
# Function should return empty vector
result <- sim_weib_ph(weibull_ph_mod = weib_model, samp_df = samp_df)
expect_length(result, 0)
})
test_that("sim_weib_ph validates cond_drift input", {
# Create a simple survreg Weibull model
set.seed(123)
n <- 50
df <- data.frame(
time = rweibull(n, shape = 1.5, scale = 5),
event = sample(0:1, n, replace = TRUE, prob = c(0.2, 0.8)),
cov1 = rnorm(n),
cov2 = rbinom(n, 1, 0.5)
)
weib_model <- survival::survreg(survival::Surv(time, event) ~ cov1 + cov2, data = df, dist = "weibull")
# Sample data
samp_df <- data.frame(
cov1 = rnorm(10),
cov2 = rbinom(10, 1, 0.5)
)
# Test error when cond_drift is not numeric
expect_error(
sim_weib_ph(weib_model, samp_df, cond_drift = "not a number"),
"`cond_drift` must be a single number"
)
# Test error when cond_drift is a vector
expect_error(
sim_weib_ph(weib_model, samp_df, cond_drift = c(0.1, 0.2)),
"`cond_drift` must be a single number"
)
})
test_that("sim_weib_ph validates cond_trt_effect input", {
# Create a simple survreg Weibull model
set.seed(123)
n <- 50
df <- data.frame(
time = rweibull(n, shape = 1.5, scale = 5),
event = sample(0:1, n, replace = TRUE, prob = c(0.2, 0.8)),
cov1 = rnorm(n),
cov2 = rbinom(n, 1, 0.5)
)
weib_model <- survival::survreg(survival::Surv(time, event) ~ cov1 + cov2, data = df, dist = "weibull")
# Sample data
samp_df <- data.frame(
cov1 = rnorm(10),
cov2 = rbinom(10, 1, 0.5)
)
# Test error when cond_trt_effect is not numeric
expect_error(
sim_weib_ph(weib_model, samp_df, cond_trt_effect = "not a number"),
"`cond_trt_effect` must be a single number"
)
# Test error when cond_trt_effect is a vector
expect_error(
sim_weib_ph(weib_model, samp_df, cond_trt_effect = c(0.1, 0.2)),
"`cond_trt_effect` must be a single number"
)
})
test_that("sim_weib_ph validates weibull_ph_mod input", {
# Create sample data
samp_df <- data.frame(
cov1 = rnorm(10),
cov2 = rbinom(10, 1, 0.5)
)
# Test error with non-survreg object
expect_error(
sim_weib_ph(weibull_ph_mod = "not a survreg object", samp_df = samp_df),
"`weibull_ph_mod` must be a `survreg` object with a Wiebull distribution"
)
# Test error with non-Weibull survreg object
set.seed(123)
n <- 50
df <- data.frame(
time = rexp(n, 0.1),
event = sample(0:1, n, replace = TRUE, prob = c(0.2, 0.8)),
cov1 = rnorm(n),
cov2 = rbinom(n, 1, 0.5)
)
# Create an exponential model (not Weibull)
exp_model <- survival::survreg(survival::Surv(time, event) ~ cov1 + cov2, data = df, dist = "exponential")
# This should error because it's not a Weibull model
expect_error(
sim_weib_ph(weibull_ph_mod = exp_model, samp_df = samp_df),
"`weibull_ph_mod` must be a `survreg` object with a Wiebull distribution"
)
})
# calc_cond_weibull -------------------------------------------------------
test_that("calc_cond_weibull produces expected results format and validates inputs", {
# Setup test data
set.seed(123)
n <- 50
df <- data.frame(
y = rweibull(n, shape = 1.5, scale = 5),
event = sample(0:1, n, replace = TRUE, prob = c(0.2, 0.8)),
cov1 = rnorm(n),
cov2 = rbinom(n, 1, 0.5),
cov3 = rnorm(n, mean = 0.5),
cov4 = rbinom(n, 1, 0.7)
)
# Create model for testing
weib_model <- survival::survreg(survival::Surv(y, event) ~ cov1 + cov2 + cov3 + cov4, data = df, dist = "weibull")
# Create small test population - small to make test run faster
pop <- data.frame(
cov1 = rnorm(1000),
cov2 = rbinom(1000, 1, 0.5),
cov3 = rnorm(1000, mean = 0.5),
cov4 = rbinom(1000, 1, 0.7)
)
# Test with wrong model class
expect_error(
calc_cond_weibull(
population = pop,
weibull_ph_mod = "not a survreg object",
marg_drift = c(0),
marg_trt_eff = c(0.1),
analysis_time = 12
),
"`weibull_ph_mod` must be a survreg object"
)
# Test with wrong model distribution
exp_model <- survival::survreg(survival::Surv(y, event) ~ cov1 + cov2 + cov3 + cov4, data = df, dist = "exponential")
expect_error(
calc_cond_weibull(
population = pop,
weibull_ph_mod = exp_model,
marg_drift = c(0),
marg_trt_eff = c(0.1),
analysis_time = 12
),
"`weibull_ph_mod` must use a weibull distribution"
)
# Test with wrong population format
expect_error(
calc_cond_weibull(
population = as.list(pop),
weibull_ph_mod = weib_model,
marg_drift = c(0),
marg_trt_eff = c(0.1),
analysis_time = 12
),
"`population` must be a tibble or dataframe"
)
# Test with missing covariates in population
pop_missing <- pop |> select(-cov4)
expect_error(
calc_cond_weibull(
population = pop_missing,
weibull_ph_mod = weib_model,
marg_drift = c(0),
marg_trt_eff = c(0.1),
analysis_time = 12
),
"Not all covariates in `weibull_ph_mod` are in the population"
)
expect_error(
calc_cond_weibull(
population = pop,
weibull_ph_mod = weib_model,
marg_drift = c(0),
marg_trt_eff = c(0.1),
analysis_time = c(6, 12)
),
"`analysis_time` must be a single number"
)
})
test_that("calc_cond_weibull correctly calculates conditional effects", {
# Setup test data - to avoid recomputing
skip_on_cran() # Skip on CRAN since this is a slower test
set.seed(123)
n <- 100
df <- data.frame(
y = rweibull(n, shape = 1.5, scale = 5),
event = sample(0:1, n, replace = TRUE, prob = c(0.2, 0.8)),
cov1 = rnorm(n),
cov2 = rbinom(n, 1, 0.5)
)
weib_model <- survival::survreg(survival::Surv(y, event) ~ cov1 + cov2, data = df, dist = "weibull")
# Create a larger population for more accurate calculation
set.seed(456)
pop <- data.frame(
cov1 = rnorm(10000),
cov2 = rbinom(10000, 1, 0.5)
)
# Run function once and save results for multiple assertions
result <- calc_cond_weibull(
population = pop,
weibull_ph_mod = weib_model,
marg_drift = c(-0.1, 0, 0.1),
marg_trt_eff = c(0, 0.1),
analysis_time = 12
)
# Test structure
expect_true(is.data.frame(result))
expect_equal(nrow(result), 5) # 3 drift values × 2 treatment effects (-the case with 0 trt effect and neg drift)
expect_equal(ncol(result), 6) # 6 columns in output
# Check column names
expected_cols <- c("marg_drift", "marg_trt_eff", "conditional_drift",
"true_control_surv_prob", "conditional_trt_eff",
"true_trt_surv_prob")
expect_true(all(expected_cols %in% colnames(result)))
})
test_that("calc_cond_weibull survival probabilities match marginal effects", {
# Use the same results object from previous test to avoid recomputation
skip_on_cran() # Skip on CRAN since this is a slower test
set.seed(123)
n <- 100
df <- data.frame(
y = rweibull(n, shape = 1.5, scale = 5),
event = sample(0:1, n, replace = TRUE, prob = c(0.2, 0.8)),
cov1 = rnorm(n),
cov2 = rbinom(n, 1, 0.5)
)
weib_model <- survival::survreg(survival::Surv(y, event) ~ cov1 + cov2, data = df, dist = "weibull")
# Create a larger population for more accurate calculation
set.seed(456)
pop <- data.frame(
cov1 = rnorm(5000), # Smaller to run faster in tests
cov2 = rbinom(5000, 1, 0.5)
)
# Run function and save results
result <- calc_cond_weibull(
population = pop,
weibull_ph_mod = weib_model,
marg_drift = c(0), # Testing just one value to speed up test
marg_trt_eff = c(0.1),
analysis_time = 12
)
# For drift = 0, treatment effect = 0.1
trt_effect_row <- result[1, ]
# The difference between treatment and control survival probabilities should be close to the marginal effect
observed_effect <- trt_effect_row$true_trt_surv_prob - trt_effect_row$true_control_surv_prob
expect_equal(observed_effect, trt_effect_row$marg_trt_eff, tolerance = 0.01)
})
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.