tests/testthat/test-engine-mlr.R

test_that("MLR engine recovers known growth advantages", {
  sim <- simulate_dynamics(
    n_lineages   = 3,
    advantages   = c("fast" = 1.4, "slow" = 0.7),
    n_timepoints = 20,
    total_per_tp = 2000,
    seed         = 42
  )
  # Explicitly set pivot = "ref" so the test is deterministic
  result <- .engine_mlr(sim, pivot = "ref")

  expect_true(is.list(result))
  expect_true("growth_rates" %in% names(result))

  # fast should have positive growth rate
  expect_gt(result$growth_rates["fast"], 0)
  # slow should have negative growth rate
  expect_lt(result$growth_rates["slow"], 0)
  # pivot (ref) should be exactly 0
  expect_equal(unname(result$growth_rates["ref"]), 0)
})

test_that("MLR engine auto-selects pivot", {
  sim <- simulate_dynamics(
    n_lineages   = 3,
    advantages   = c("A" = 1.2, "B" = 0.9),
    n_timepoints = 10, seed = 1
  )
  result <- .engine_mlr(sim)

  expect_true(result$pivot %in% attr(sim, "lineages"))
  expect_equal(unname(result$growth_rates[result$pivot]), 0)
})

test_that("MLR engine respects custom pivot", {
  sim <- simulate_dynamics(
    n_lineages   = 3,
    advantages   = c("A" = 1.2, "B" = 0.9),
    n_timepoints = 10, seed = 1
  )
  result <- .engine_mlr(sim, pivot = "A")

  expect_equal(result$pivot, "A")
  expect_equal(unname(result$growth_rates["A"]), 0)
})

test_that("MLR engine works with exactly 2 lineages", {
  sim <- simulate_dynamics(
    n_lineages   = 2,
    advantages   = c("rising" = 1.3),
    n_timepoints = 10,
    total_per_tp = 500,
    seed         = 5
  )
  result <- .engine_mlr(sim)

  expect_equal(length(result$lineages), 2)
  expect_equal(result$df, 2L)  # 1 alpha + 1 delta
})

test_that("MLR engine returns complete structure", {
  sim <- simulate_dynamics(
    n_lineages   = 3,
    advantages   = c("A" = 1.2, "B" = 0.8),
    n_timepoints = 12, seed = 7
  )
  result <- .engine_mlr(sim)

  required_fields <- c(
    "growth_rates", "intercepts", "pivot", "lineages",
    "fitted_values", "residuals", "vcov_matrix",
    "loglik", "aic", "bic", "nobs", "n_timepoints",
    "df", "convergence", "date_range", "time_scale"
  )
  for (f in required_fields) {
    expect_true(f %in% names(result),
                info = paste("Missing field:", f))
  }

  expect_true(is.matrix(result$vcov_matrix))
  expect_s3_class(result$fitted_values, "tbl_df")
  expect_s3_class(result$residuals, "tbl_df")
  expect_equal(result$convergence, 0L)
})

test_that("MLR engine window parameter reduces data", {
  sim <- simulate_dynamics(
    n_lineages   = 3,
    advantages   = c("A" = 1.2, "B" = 0.8),
    n_timepoints = 20, seed = 1
  )

  result_full   <- .engine_mlr(sim)
  result_window <- .engine_mlr(sim, window = 42)

  expect_lt(result_window$n_timepoints, result_full$n_timepoints)
})

Try the lineagefreq package in your browser

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

lineagefreq documentation built on April 3, 2026, 9:09 a.m.