test_that("Poisson GLMM fits", { skip_if_not_installed("glmmTMB") set.seed(123) dat <- data.frame( y = rpois(100, 5), x = rnorm(100), id = factor(rep(1:20, each = 5)) ) m <- fit_glmm( y ~ x + (1 | id), data = dat, family = "poisson" ) expect_s3_class(m, "biomix_glmm") expect_equal(m$family, "poisson") }) test_that("negative-binomial GLMM fits", { skip_if_not_installed("glmmTMB") set.seed(123) dat <- data.frame( y = rnbinom(100, size = 2, mu = 5), x = rnorm(100), id = factor(rep(1:20, each = 5)) ) m <- fit_glmm( y ~ x + (1 | id), data = dat, family = "nbinom2" ) expect_s3_class(m, "biomix_glmm") expect_equal(m$family, "nbinom2") }) test_that("zero-inflated GLMM fits", { skip_if_not_installed("glmmTMB") set.seed(123) dat <- data.frame( y = rpois(100, 2), x = rnorm(100), id = factor(rep(1:20, each = 5)) ) dat$y[sample(1:100, 40)] <- 0 m <- fit_glmm( y ~ x + (1 | id), data = dat, family = "poisson", ziformula = ~1 ) expect_s3_class(m, "biomix_glmm") expect_true(m$zero_inflated) expect_equal(m$model_type, "Zero-inflated GLMM") }) test_that("GAMM validates formula", { skip_if_not_installed("mgcv") dat <- data.frame( y = rnorm(20), x = rnorm(20) ) expect_error( fit_gamm( formula = "y ~ s(x)", data = dat ), "formula" ) }) test_that("GAMM validates data", { skip_if_not_installed("mgcv") expect_error( fit_gamm( formula = y ~ s(x), data = list( y = rnorm(20), x = rnorm(20) ) ), "data" ) }) test_that("GAMM fits with smooth term", { skip_if_not_installed("mgcv") set.seed(123) dat <- data.frame( id = factor(rep(1:10, each = 10)), x = rep(seq(0, 1, length.out = 10), 10) ) dat$y <- sin(2 * pi * dat$x) + rnorm(100, sd = 0.2) m <- fit_gamm( y ~ s(x, k = 5), data = dat, random = list(id = ~1) ) expect_s3_class(m, "biomix_gamm") expect_true(is.list(m)) expect_true(is.finite(AIC(get_fit(m)$lme))) }) test_that("fit_glmm rejects non-formula ziformula", { dat <- data.frame( y = rpois(20, 5), x = rnorm(20), id = factor(rep(1:5, each = 4)) ) expect_error( fit_glmm( y ~ x + (1 | id), data = dat, family = "poisson", ziformula = "not a formula" ), "ziformula must be a formula." ) }) test_that("fit_glmm rejects non-formula dispformula", { dat <- data.frame( y = rpois(20, 5), x = rnorm(20), id = factor(rep(1:5, each = 4)) ) expect_error( fit_glmm( y ~ x + (1 | id), data = dat, family = "poisson", dispformula = "not a formula" ), "dispformula must be a formula." ) }) test_that("fit_glmm gives informative error when glmmTMB is unavailable", { testthat::local_mocked_bindings( .has_glmmTMB = function() FALSE, .package = "BioMixModel" ) dat <- data.frame( y = rpois(10, 5), x = rnorm(10), id = factor(rep(1:5, each = 2)) ) expect_error( fit_glmm( y ~ x + (1 | id), data = dat, family = "poisson" ), "Package 'glmmTMB' is required for GLMMs." ) }) test_that("fit_glmm supports nbinom1", { dat <- data.frame( y = rpois(60, 5), x = rnorm(60), id = factor(rep(1:20, each = 3)) ) m <- fit_glmm( y ~ x + (1 | id), data = dat, family = "nbinom1" ) expect_s3_class(m, "biomix_glmm") expect_identical(m$family, "nbinom1") expect_identical(m$model_type, "GLMM") expect_false(m$zero_inflated) }) test_that("fit_glmm supports nbinom2", { set.seed(123) dat <- data.frame( x = rnorm(100), id = factor(rep(1:20, each = 5)) ) dat$y <- rnbinom( 100, size = 2, mu = exp(1 + 0.5 * dat$x) ) m <- fit_glmm( y ~ x + (1 | id), data = dat, family = "nbinom2" ) expect_s3_class(m, "biomix_glmm") expect_identical(m$family, "nbinom2") expect_false(m$zero_inflated) expect_equal(m$model_type, "GLMM") }) test_that("fit_glmm rejects non-formula input", { dat <- data.frame( y = rpois(10, 5), x = rnorm(10), id = factor(rep(1:5, each = 2)) ) expect_error( fit_glmm( formula = "y ~ x + (1 | id)", data = dat, family = "poisson" ), "formula must be a formula." ) }) test_that("fit_glmm rejects non-data-frame input", { expect_error( fit_glmm( formula = y ~ x, data = list( y = rpois(10, 5), x = rnorm(10) ), family = "poisson" ), "data must be a data frame." ) })