Nothing
# Tests for conditional_effects.bmmfit() and its internal helpers
# Tier 1: Unit tests (always run, no fitted model)
# Tier 2: Fixture-based integration tests (skip on CRAN)
# Tier 3: Model-fitting integration tests (skip on CRAN)
load_sdm_fit <- function() {
path <- test_path("assets/bmmfit_example1.rds")
skip_if_not(file.exists(path), "SDM fixture not available (excluded by .Rbuildignore)")
readRDS(path)
}
# ===========================================================================
# Tier 1: Unit tests — .extract_re_grouping_vars()
# ===========================================================================
test_that(".extract_re_grouping_vars extracts single-bar grouping var", {
f <- y ~ x + (1 | id)
expect_equal(.extract_re_grouping_vars(f), "id")
})
test_that(".extract_re_grouping_vars extracts double-bar grouping var", {
f <- y ~ x + (1 || id)
expect_equal(.extract_re_grouping_vars(f), "id")
})
test_that(".extract_re_grouping_vars extracts correlation-ID and grouping var", {
f <- y ~ x + (1 |ID1| id)
result <- .extract_re_grouping_vars(f)
expect_true("id" %in% result)
expect_true("ID1" %in% result)
})
test_that(".extract_re_grouping_vars extracts gr() grouping var", {
f <- y ~ x + (1 | gr(id, by = exp))
expect_equal(.extract_re_grouping_vars(f), "id")
})
test_that(".extract_re_grouping_vars extracts gr() with cor arg", {
f <- y ~ x + (1 | gr(id, cor = FALSE))
expect_equal(.extract_re_grouping_vars(f), "id")
})
test_that(".extract_re_grouping_vars extracts mm() grouping vars", {
f <- y ~ x + (1 | mm(g1, g2))
result <- .extract_re_grouping_vars(f)
expect_true("g1" %in% result)
expect_true("g2" %in% result)
expect_length(result, 2)
})
test_that(".extract_re_grouping_vars extracts crossed grouping vars", {
f <- y ~ x + (1 | id:group)
result <- .extract_re_grouping_vars(f)
expect_true("id" %in% result)
expect_true("group" %in% result)
})
test_that(".extract_re_grouping_vars handles multiple RE terms", {
f <- y ~ x + (1 | id) + (1 | group)
result <- .extract_re_grouping_vars(f)
expect_true("id" %in% result)
expect_true("group" %in% result)
})
test_that(".extract_re_grouping_vars returns empty for no RE", {
f <- y ~ x
expect_equal(.extract_re_grouping_vars(f), character(0))
})
test_that(".extract_re_grouping_vars returns empty for intercept only", {
f <- y ~ 1
expect_equal(.extract_re_grouping_vars(f), character(0))
})
# ===========================================================================
# Tier 1: Unit tests — .ce_summarize_draws()
# ===========================================================================
test_that(".ce_summarize_draws computes mean/SD summary", {
set.seed(42)
draws <- matrix(rnorm(1000 * 3), nrow = 1000, ncol = 3)
result <- .ce_summarize_draws(draws)
expect_named(result, c("estimate", "lower", "upper", "se"))
expect_length(result$estimate, 3)
expect_length(result$lower, 3)
expect_length(result$upper, 3)
expect_length(result$se, 3)
# Estimates should be close to column means
expect_equal(result$estimate, colMeans(draws), tolerance = 1e-10)
# SE should be close to column SDs
expect_equal(result$se, apply(draws, 2, sd), tolerance = 1e-10)
})
test_that(".ce_summarize_draws uses median/MAD when robust = TRUE", {
set.seed(42)
draws <- matrix(rnorm(1000 * 2), nrow = 1000, ncol = 2)
result <- .ce_summarize_draws(draws, robust = TRUE)
expect_equal(result$estimate, apply(draws, 2, median), tolerance = 1e-10)
expect_equal(result$se, apply(draws, 2, mad), tolerance = 1e-10)
})
test_that(".ce_summarize_draws handles single-row draws", {
draws <- matrix(c(1, 2, 3), nrow = 1, ncol = 3)
result <- .ce_summarize_draws(draws)
expect_equal(result$estimate, c(1, 2, 3))
expect_length(result$lower, 3)
expect_length(result$upper, 3)
})
test_that(".ce_summarize_draws prob argument controls CI width", {
set.seed(42)
draws <- matrix(rnorm(5000 * 2), nrow = 5000, ncol = 2)
wide <- .ce_summarize_draws(draws, prob = 0.95)
narrow <- .ce_summarize_draws(draws, prob = 0.50)
# Wider prob → wider interval
expect_true(all(wide$upper - wide$lower > narrow$upper - narrow$lower))
})
# ===========================================================================
# Tier 1: Unit tests — .apply_link_transform()
# ===========================================================================
# Helper to create mock brms_conditional_effects objects
mock_ce <- function(...) {
dfs <- list(...)
class(dfs) <- c("brms_conditional_effects", "list")
dfs
}
mock_ce_df <- function(estimate, lower, upper) {
data.frame(
x = seq_along(estimate),
estimate__ = estimate,
lower__ = lower,
upper__ = upper
)
}
test_that(".apply_link_transform is no-op for identity link", {
ce <- mock_ce(
eff1 = mock_ce_df(c(1, 2, 3), c(0.5, 1.5, 2.5), c(1.5, 2.5, 3.5))
)
result <- .apply_link_transform(ce, "identity", inverse = TRUE)
expect_equal(result[[1]]$estimate__, c(1, 2, 3))
expect_equal(result[[1]]$lower__, c(0.5, 1.5, 2.5))
expect_equal(result[[1]]$upper__, c(1.5, 2.5, 3.5))
})
test_that(".apply_link_transform applies inverse log (exp)", {
ce <- mock_ce(
eff1 = mock_ce_df(c(0, 1, 2), c(-0.5, 0.5, 1.5), c(0.5, 1.5, 2.5))
)
result <- .apply_link_transform(ce, "log", inverse = TRUE)
expect_equal(result[[1]]$estimate__, exp(c(0, 1, 2)), tolerance = 1e-10)
expect_equal(result[[1]]$lower__, exp(c(-0.5, 0.5, 1.5)), tolerance = 1e-10)
expect_equal(result[[1]]$upper__, exp(c(0.5, 1.5, 2.5)), tolerance = 1e-10)
})
test_that(".apply_link_transform applies forward log", {
ce <- mock_ce(
eff1 = mock_ce_df(c(1, 2, 3), c(0.5, 1.5, 2.5), c(1.5, 2.5, 3.5))
)
result <- .apply_link_transform(ce, "log", inverse = FALSE)
expect_equal(result[[1]]$estimate__, log(c(1, 2, 3)), tolerance = 1e-10)
expect_equal(result[[1]]$lower__, log(c(0.5, 1.5, 2.5)), tolerance = 1e-10)
expect_equal(result[[1]]$upper__, log(c(1.5, 2.5, 3.5)), tolerance = 1e-10)
})
test_that(".apply_link_transform applies inverse logit (plogis)", {
ce <- mock_ce(
eff1 = mock_ce_df(c(-1, 0, 1), c(-2, -1, 0), c(0, 1, 2))
)
result <- .apply_link_transform(ce, "logit", inverse = TRUE)
expect_equal(result[[1]]$estimate__, plogis(c(-1, 0, 1)), tolerance = 1e-10)
expect_equal(result[[1]]$lower__, plogis(c(-2, -1, 0)), tolerance = 1e-10)
})
test_that(".apply_link_transform preserves class and names", {
ce <- mock_ce(
set_size = mock_ce_df(c(1, 2), c(0.5, 1.5), c(1.5, 2.5)),
condition = mock_ce_df(c(3, 4), c(2.5, 3.5), c(3.5, 4.5))
)
result <- .apply_link_transform(ce, "log", inverse = TRUE)
expect_s3_class(result, "brms_conditional_effects")
expect_named(result, c("set_size", "condition"))
})
test_that(".apply_link_transform transforms all elements in list", {
ce <- mock_ce(
eff1 = mock_ce_df(c(0, 1), c(-0.5, 0.5), c(0.5, 1.5)),
eff2 = mock_ce_df(c(2, 3), c(1.5, 2.5), c(2.5, 3.5))
)
result <- .apply_link_transform(ce, "log", inverse = TRUE)
expect_equal(result[[1]]$estimate__, exp(c(0, 1)), tolerance = 1e-10)
expect_equal(result[[2]]$estimate__, exp(c(2, 3)), tolerance = 1e-10)
})
# ===========================================================================
# Tier 1: Unit tests — .filter_internal_effects()
# ===========================================================================
test_that(".filter_internal_effects removes internal variables", {
# Build a mock bmmfit with minimal structure
mock_bmmfit <- list(
bmm = list(
model = structure(
list(other_vars = list()),
class = c("sdm", "bmmodel")
)
)
)
ce <- mock_ce(
set_size = mock_ce_df(1:3, 0:2, 2:4),
LureIdx1 = mock_ce_df(1:3, 0:2, 2:4),
Idx_corr = mock_ce_df(1:3, 0:2, 2:4),
inv_ss = mock_ce_df(1:3, 0:2, 2:4),
Item1_Col_rad = mock_ce_df(1:3, 0:2, 2:4),
expS = mock_ce_df(1:3, 0:2, 2:4)
)
result <- .filter_internal_effects(ce, mock_bmmfit)
expect_named(result, "set_size")
expect_s3_class(result, "brms_conditional_effects")
})
test_that(".filter_internal_effects keeps all user vars", {
mock_bmmfit <- list(
bmm = list(
model = structure(
list(other_vars = list()),
class = c("sdm", "bmmodel")
)
)
)
ce <- mock_ce(
set_size = mock_ce_df(1:3, 0:2, 2:4),
condition = mock_ce_df(1:3, 0:2, 2:4)
)
result <- .filter_internal_effects(ce, mock_bmmfit)
expect_named(result, c("set_size", "condition"))
})
# ===========================================================================
# Tier 2: Fixture-based integration tests
# ===========================================================================
test_that("conditional_effects returns correct class for par = 'c'", {
skip_on_cran()
fit <- load_sdm_fit()
ce <- conditional_effects(fit, par = "c")
expect_s3_class(ce, "brms_conditional_effects")
expect_true(length(ce) > 0)
})
test_that("conditional_effects works for intercept-only par = 'kappa'", {
skip_on_cran()
fit <- load_sdm_fit()
ce <- conditional_effects(fit, par = "kappa")
expect_s3_class(ce, "brms_conditional_effects")
})
test_that("conditional_effects with par = NULL returns all estimated params", {
skip_on_cran()
fit <- load_sdm_fit()
ce <- conditional_effects(fit)
expect_s3_class(ce, "brms_conditional_effects")
# SDM fixture has estimated params: c and kappa
# Effect names are prefixed with par name: "c.set_size", "kappa.1"
effect_names <- names(ce)
expect_true(any(grepl("^c\\.", effect_names)))
expect_true(any(grepl("^kappa\\.", effect_names)))
})
test_that("conditional_effects errors for invalid par name", {
skip_on_cran()
fit <- load_sdm_fit()
expect_error(
conditional_effects(fit, par = "nonexistent"),
"not found in model"
)
})
test_that("conditional_effects errors for non-character par", {
skip_on_cran()
fit <- load_sdm_fit()
expect_error(
conditional_effects(fit, par = 42),
"must be a single character string"
)
})
test_that("scale = 'native' gives positive values for log-linked par", {
skip_on_cran()
fit <- load_sdm_fit()
ce <- conditional_effects(fit, par = "c", scale = "native")
# c has log link, so native scale = exp(sampling) → all positive
estimates <- ce[[1]]$estimate__
expect_true(all(estimates > 0))
})
test_that("scale = 'sampling' can give negative values for log-linked par", {
skip_on_cran()
fit <- load_sdm_fit()
ce <- conditional_effects(fit, par = "c", scale = "sampling")
# On log scale, values can be any real number
# Just verify it returns successfully and has different values from native
ce_native <- conditional_effects(fit, par = "c", scale = "native")
expect_false(
isTRUE(all.equal(ce[[1]]$estimate__, ce_native[[1]]$estimate__))
)
})
test_that("effects argument limits output to specified effect", {
skip_on_cran()
fit <- load_sdm_fit()
ce <- conditional_effects(fit, par = "c", effects = "set_size")
expect_length(ce, 1)
expect_true("set_size" %in% names(ce))
})
test_that("plotting conditional_effects works", {
skip_on_cran()
fit <- load_sdm_fit()
ce <- conditional_effects(fit, par = "c")
p <- plot(ce, plot = FALSE)
expect_true(length(p) > 0)
})
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.