tests/testthat/test-binary-posterior.R

test_that("getPosterior: binary mode uses binomial GLM and returns postList", {
  skip_if_not_installed("RBesT")
  
  set.seed(10)
  
  dose_levels <- c(0, 1, 2, 4)
  n_per_dose  <- 50
  probs       <- c(0.10, 0.20, 0.35, 0.55)
  
  dat <- data.frame(
    simulation = 1L,
    dose       = rep(dose_levels, each = n_per_dose),
    response   = unlist(lapply(probs, function(p) rbinom(n_per_dose, 1, p)))
  )
  attr(dat, "probability_scale") <- TRUE
  
  prior_list <- setNames(
    lapply(seq_along(dose_levels), function(i) {
      RBesT::mixnorm(comp1 = c(w = 1, m = qlogis(probs[i]), s = 1.5), sigma = 2)
    }),
    c("Ctr", paste0("DG_", seq_along(dose_levels[-1])))
  )
  
  post <- getPosterior(
    prior_list        = prior_list,
    data              = dat,
    calc_ess          = TRUE,
    probability_scale = TRUE
  )
  
  expect_s3_class(post, "postList")
  expect_equal(length(post), length(dose_levels))
  expect_true(is.list(attr(post, "posteriorInfo")))
  # ess can be numeric(0) in your current implementation depending on path
  expect_true(is.null(attr(post, "ess")) || is.numeric(attr(post, "ess")))
})

test_that("getPosterior: binary mode rejects malformed data (still needs simulation column)", {
  skip_if_not_installed("RBesT")
  
  dose_levels <- c(0, 1, 2, 4)
  prior_list <- setNames(
    lapply(seq_along(dose_levels), function(i) {
      RBesT::mixnorm(comp1 = c(w = 1, m = 0, s = 2), sigma = 2)
    }),
    c("Ctr", paste0("DG_", seq_along(dose_levels[-1])))
  )
  
  bad_dat <- data.frame(simulation = 1L, dose = c(0, 1), y = c(0, 1))
  attr(bad_dat, "probability_scale") <- TRUE
  
  expect_error(
    getPosterior(prior_list = prior_list, data = bad_dat, probability_scale = TRUE),
    regexp = "response"
  )
  
  bad_dat2 <- data.frame(simulation = 1L, dose = c(0, 0, 1, 1), response = c(0, 2, 1, 0))
  attr(bad_dat2, "probability_scale") <- TRUE
  
  # glm(binomial) should error when response is not 0/1 (or produce warnings then error downstream)
  expect_error(
    getPosterior(prior_list = prior_list, data = bad_dat2, probability_scale = TRUE)
  )
})

test_that("getPosterior: complete separation either succeeds with finite summary or errors (no silent NA)", {
  skip_if_not_installed("RBesT")
  
  dose_levels <- c(0, 1)
  prior_list <- setNames(
    list(
      RBesT::mixnorm(comp1 = c(w = 1, m = -2, s = 2), sigma = 2),
      RBesT::mixnorm(comp1 = c(w = 1, m =  2, s = 2), sigma = 2)
    ),
    c("Ctr", "DG_1")
  )
  
  dat <- data.frame(
    simulation = 1L,
    dose       = rep(dose_levels, each = 30),
    response   = c(rep(0, 30), rep(1, 30))
  )
  attr(dat, "probability_scale") <- TRUE
  
  res <- try(getPosterior(prior_list = prior_list, data = dat, probability_scale = TRUE), silent = TRUE)
  
  if (inherits(res, "try-error")) {
    # We accept an error, but it shouldn't be a cryptic failure later (like NA propagation).
    expect_true(nchar(as.character(res)) > 0)
  } else {
    expect_s3_class(res, "postList")
    s <- summary(res)
    expect_true(all(is.finite(s[, "mean"])))
    expect_true(all(is.finite(s[, "sd"])))
  }
})

Try the BayesianMCPMod package in your browser

Any scripts or data that you put into this service are public.

BayesianMCPMod documentation built on Feb. 23, 2026, 5:06 p.m.