tests/testthat/test-econometric-identification.R

test_that("no-DK model converges to unique solution from different starting values", {
  set.seed(444)
  n <- 1000

  data <- simulate_prepost_data(n, c(0.35, 0.30, 0.35), 0.25)
  trans <- multi_transmat(data$pre, data$post)

  result1 <- lca_cor(trans, nodk_priors = c(0.3, 0.3, 0.3, 0.25))
  result2 <- lca_cor(trans, nodk_priors = c(0.5, 0.2, 0.2, 0.30))
  result3 <- lca_cor(trans, nodk_priors = c(0.2, 0.4, 0.3, 0.20))

  expect_equal(result1$param.lca[, 1], result2$param.lca[, 1], tolerance = 0.05)
  expect_equal(result1$param.lca[, 1], result3$param.lca[, 1], tolerance = 0.05)
})

test_that("model estimates are within valid parameter space", {
  set.seed(555)

  for (i in 1:10) {
    n <- 500
    data <- simulate_prepost_data(
      n,
      c(runif(1, 0.2, 0.5), runif(1, 0.1, 0.4), runif(1, 0.2, 0.5)),
      runif(1, 0.15, 0.35)
    )
    data$pre$item1 <- pmax(0, pmin(1, data$pre$item1))
    data$post$item1 <- pmax(0, pmin(1, data$post$item1))

    trans <- multi_transmat(data$pre, data$post)
    result <- lca_cor(trans)

    params <- result$param.lca[, 1]

    expect_true(all(params >= 0 & params <= 1))
    expect_equal(sum(params[1:3]), 1, tolerance = 1e-6)
  }
})

test_that("lambda parameters sum to 1", {
  set.seed(666)

  for (i in 1:20) {
    n <- 300
    data <- simulate_prepost_data(n, c(0.4, 0.3, 0.3), 0.25)
    trans <- multi_transmat(data$pre, data$post)
    result <- lca_cor(trans)

    lambda_sum <- sum(result$param.lca[1:3, 1])

    expect_equal(lambda_sum, 1.0, tolerance = 1e-6)
  }
})

test_that("DK model GOF test has reasonable Type I error rate", {
  skip_if(
    Sys.getenv("GUESS_FULL_TESTS") != "true",
    "Extended tests require GUESS_FULL_TESTS=true"
  )

  set.seed(55555)

  n_sims <- 100
  n <- 500
  alpha <- 0.05

  rejection_count <- 0

  for (sim in seq_len(n_sims)) {
    data <- simulate_dk_prepost_data(n)

    trans <- multi_transmat(data$pre, data$post, force9 = TRUE)

    tryCatch(
      {
        result <- lca_cor(trans)

        fit_result <- fit_model(
          data$pre, data$post,
          result$param.lca[8, ],
          result$param.lca[1:7, ],
          force9 = TRUE
        )

        if (any(fit_result["p-value", ] < alpha, na.rm = TRUE)) {
          rejection_count <- rejection_count + 1
        }
      },
      error = function(e) NULL
    )
  }

  rejection_rate <- rejection_count / n_sims

  expect_true(
    rejection_rate >= 0.01 && rejection_rate <= 0.20,
    info = paste("Type I error rate:", rejection_rate)
  )
})

test_that("model recovers extreme parameter values", {
  set.seed(777)

  extreme_cases <- list(
    c(0.8, 0.1, 0.1),
    c(0.1, 0.1, 0.8),
    c(0.1, 0.8, 0.1)
  )

  for (true_lambdas in extreme_cases) {
    n <- 1000
    data <- simulate_prepost_data(n, true_lambdas, 0.25)
    trans <- multi_transmat(data$pre, data$post)
    result <- lca_cor(trans)

    estimates <- result$param.lca[1:3, 1]

    correlation <- cor(estimates, true_lambdas)

    expect_true(
      correlation > 0.5,
      info = paste(
        "True:", paste(round(true_lambdas, 2), collapse = ","),
        "Est:", paste(round(estimates, 2), collapse = ",")
      )
    )
  }
})

test_that("gamma estimate is reasonable across different true values", {
  set.seed(888)

  gamma_values <- c(0.15, 0.25, 0.40)

  for (true_gamma in gamma_values) {
    n <- 800
    data <- simulate_prepost_data(n, c(0.4, 0.3, 0.3), true_gamma)
    trans <- multi_transmat(data$pre, data$post)
    result <- lca_cor(trans)

    estimated_gamma <- result$param.lca["gamma", 1]

    expect_true(
      abs(estimated_gamma - true_gamma) < 0.15,
      info = paste("True gamma:", true_gamma, "Estimated:", round(estimated_gamma, 3))
    )
  }
})

test_that("multi-item estimation produces consistent results", {
  set.seed(999)

  n <- 500
  n_items <- 3

  true_lambdas <- c(0.35, 0.30, 0.35)
  true_gamma <- 0.25

  pre_list <- vector("list", n_items)
  post_list <- vector("list", n_items)

  for (item in seq_len(n_items)) {
    data <- simulate_prepost_data(n, true_lambdas, true_gamma)
    pre_list[[item]] <- data$pre$item1
    post_list[[item]] <- data$post$item1
  }

  pre_df <- as.data.frame(pre_list)
  post_df <- as.data.frame(post_list)
  names(pre_df) <- paste0("item", 1:n_items)
  names(post_df) <- paste0("item", 1:n_items)

  trans <- multi_transmat(pre_df, post_df)
  result <- lca_cor(trans)

  gammas <- result$param.lca["gamma", ]

  expect_equal(length(gammas), n_items)
  expect_true(all(gammas > 0 & gammas < 1))

  gamma_range <- max(gammas) - min(gammas)
  expect_lt(gamma_range, 0.3)
})

Try the guess package in your browser

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

guess documentation built on March 31, 2026, 9:07 a.m.