tests/testthat/test-comprehensive-validation.R

# Comprehensive validation tests using data-raw approach

test_that("All core functions work together in realistic workflow", {
  set.seed(42)
  
  # Create realistic test data (small scale)
  n_people <- 50
  n_items <- 5
  
  # Generate pre-test data (40% know the answers)
  pre_test <- data.frame(
    item1 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.6, 0.4)),
    item2 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.6, 0.4)),
    item3 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.6, 0.4)),
    item4 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.6, 0.4)),
    item5 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.6, 0.4))
  )
  
  # Generate post-test data (60% know the answers - learning occurred)
  post_test <- data.frame(
    item1 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.4, 0.6)),
    item2 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.4, 0.6)),
    item3 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.4, 0.6)),
    item4 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.4, 0.6)),
    item5 = sample(c(0,1), n_people, replace=TRUE, prob=c(0.4, 0.6))
  )
  
  # Test complete workflow
  expect_no_error({
    # 1. Create transition matrix
    trans_matrix <- multi_transmat(pre_test, post_test)
    
    # 2. Apply LCA correction  
    lca_results <- lca_cor(trans_matrix)
    
    # 3. Apply standard correction
    std_results <- stnd_cor(pre_test, post_test, lucky = rep(0.25, n_items))
    
    # 4. Test fit
    fit_results <- fit_model(pre_test, post_test, 
                           lca_results$param.lca[4, ],
                           lca_results$param.lca[1:3, ])
    
    # 5. Test group adjustment  
    group_results <- group_adj(pre_test, post_test, rep(0.25, n_items))
  })
  
  # Validate results structure
  expect_equal(nrow(trans_matrix), n_items)
  expect_equal(ncol(trans_matrix), 4)
  expect_true(all(names(lca_results) %in% c("param.lca", "est.learning")))
  expect_equal(length(std_results$learn), n_items)
  expect_true(is.list(group_results))
  expect_equal(length(group_results$learn), n_items)
  
  # Validate learning estimates are reasonable
  expect_true(all(lca_results$est.learning >= -1 & lca_results$est.learning <= 1))
  expect_true(all(std_results$learn >= -1 & std_results$learn <= 1))
})

test_that("Functions handle Don't Know responses correctly", {
  set.seed(123)
  
  n_people <- 40
  n_items <- 4
  
  # Create data with Don't Know responses
  pre_test_dk <- data.frame(
    item1 = sample(c(0, 1, "d"), n_people, replace=TRUE, prob=c(0.5, 0.3, 0.2)),
    item2 = sample(c(0, 1, "d"), n_people, replace=TRUE, prob=c(0.5, 0.3, 0.2)),
    item3 = sample(c(0, 1, "d"), n_people, replace=TRUE, prob=c(0.5, 0.3, 0.2)),
    item4 = sample(c(0, 1, "d"), n_people, replace=TRUE, prob=c(0.5, 0.3, 0.2))
  )
  
  post_test_dk <- data.frame(
    item1 = sample(c(0, 1, "d"), n_people, replace=TRUE, prob=c(0.4, 0.4, 0.2)),
    item2 = sample(c(0, 1, "d"), n_people, replace=TRUE, prob=c(0.4, 0.4, 0.2)),
    item3 = sample(c(0, 1, "d"), n_people, replace=TRUE, prob=c(0.4, 0.4, 0.2)),
    item4 = sample(c(0, 1, "d"), n_people, replace=TRUE, prob=c(0.4, 0.4, 0.2))
  )
  
  expect_no_error({
    # Create 9-column transition matrix
    trans_matrix_dk <- multi_transmat(pre_test_dk, post_test_dk, force9 = TRUE)
    
    # Apply LCA correction with DK
    lca_results_dk <- lca_cor(trans_matrix_dk)
    
    # Test fit with DK
    fit_results_dk <- fit_model(pre_test_dk, post_test_dk,
                              lca_results_dk$param.lca[8, ],
                              lca_results_dk$param.lca[1:7, ],
                              force9 = TRUE)
  })
  
  # Validate DK-specific results
  expect_equal(ncol(trans_matrix_dk), 9)  # 3x3 transition matrix
  expect_equal(nrow(lca_results_dk$param.lca), 8)  # 7 lambdas + 1 gamma
  expect_true(is.matrix(fit_results_dk) || is.data.frame(fit_results_dk))
})

test_that("Edge cases and error handling work correctly", {
  # Test with minimal data
  small_pre <- data.frame(item1 = c(0, 1, 0, 1))
  small_post <- data.frame(item1 = c(1, 1, 0, 1))
  
  expect_no_error({
    small_trans <- multi_transmat(small_pre, small_post) 
    small_lca <- lca_cor(small_trans)
  })
  
  # Test validation functions work
  expect_error(multi_transmat(data.frame(), small_post))  # Empty pre-test
  expect_error(multi_transmat(small_pre, data.frame()))   # Empty post-test
  
  # Test with all same responses (edge case)
  same_pre <- data.frame(item1 = rep(1, 10))
  same_post <- data.frame(item1 = rep(1, 10))
  
  expect_no_error({
    same_trans <- multi_transmat(same_pre, same_post)
    # LCA may have convergence issues with degenerate data, but shouldn't crash
  })
})

test_that("Backward compatibility maintained", {
  # Test that old function names still work
  set.seed(99)
  
  pre_test <- data.frame(
    item1 = sample(c(0,1), 20, replace=TRUE),
    item2 = sample(c(0,1), 20, replace=TRUE)
  )
  post_test <- data.frame(
    item1 = sample(c(0,1), 20, replace=TRUE), 
    item2 = sample(c(0,1), 20, replace=TRUE)
  )
  
  trans_mat <- multi_transmat(pre_test, post_test)
  lca_result <- lca_cor(trans_mat)
  
  # Test that old fit functions still work
  expect_no_error({
    old_fit_nodk <- fit_nodk(pre_test, post_test,
                           lca_result$param.lca[4, ],
                           lca_result$param.lca[1:3, ])
  })
  
  expect_no_error({
    new_fit <- fit_model(pre_test, post_test,
                        lca_result$param.lca[4, ],
                        lca_result$param.lca[1:3, ])
  })
  
  # Results should be equivalent
  expect_equal(dim(old_fit_nodk), dim(new_fit))
})

Try the guess package in your browser

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

guess documentation built on Dec. 16, 2025, 1:07 a.m.