library(seminr) # Setup: Create a basic model for testing set.seed(123) corp_rep_mm <- constructs( composite("COMP", multi_items("comp_", 1:3)), composite("LIKE", multi_items("like_", 1:3)), composite("CUSA", single_item("cusa")), composite("CUSL", multi_items("cusl_", 1:3)) ) corp_rep_sm <- relationships( paths(from = c("COMP", "LIKE"), to = c("CUSA")), paths(from = c("CUSA"), to = c("CUSL")) ) test_model <- estimate_pls( data = corp_rep_data, measurement_model = corp_rep_mm, structural_model = corp_rep_sm, missing = mean_replacement, missing_value = "-99" ) # ============================================================================ # Basic Functionality Tests # ============================================================================ test_that("congruence_test returns proper structure", { result <- congruence_test(test_model, nboot = 50, seed = 123) # Should return a list expect_type(result, "list") # Should have 'results' element expect_named(result, "results") # Results should be a matrix with table_output class expect_true(inherits(result$results, "matrix")) expect_true("table_output" %in% class(result$results)) }) test_that("congruence_test returns correct dimensions", { result <- congruence_test(test_model, nboot = 50, seed = 123) # Number of rows should equal number of construct pairs n_constructs <- ncol(test_model$construct_scores) expected_pairs <- choose(n_constructs, 2) expect_equal(nrow(result$results), expected_pairs) # Should have 6 columns expect_equal(ncol(result$results), 6) }) test_that("congruence_test returns correct column names", { result <- congruence_test(test_model, nboot = 50, seed = 123, alpha = 0.05) expected_cols <- c("Original Est.", "Diff", "Bootstrap SD", "T Stat.", "2.5% CI", "97.5% CI") expect_equal(colnames(result$results), expected_cols) }) test_that("congruence_test row names contain construct pairs", { result <- congruence_test(test_model, nboot = 50, seed = 123) # Row names should contain " -> " pattern expect_true(all(grepl(" -> ", rownames(result$results)))) }) # ============================================================================ # Reproducibility Tests # ============================================================================ test_that("congruence_test is reproducible with same seed", { result1 <- congruence_test(test_model, nboot = 50, seed = 42) result2 <- congruence_test(test_model, nboot = 50, seed = 42) expect_equal(result1$results, result2$results) }) test_that("congruence_test differs with different seeds", { result1 <- congruence_test(test_model, nboot = 50, seed = 42) result2 <- congruence_test(test_model, nboot = 50, seed = 99) # Bootstrap SD and CI columns should differ expect_false(identical(result1$results[, "Bootstrap SD"], result2$results[, "Bootstrap SD"])) }) # ============================================================================ # Parameter Variation Tests # ============================================================================ test_that("congruence_test respects alpha parameter for CI columns", { result_05 <- congruence_test(test_model, nboot = 50, seed = 123, alpha = 0.05) result_10 <- congruence_test(test_model, nboot = 50, seed = 123, alpha = 0.10) # Column names should reflect alpha expect_true("2.5% CI" %in% colnames(result_05$results)) expect_true("97.5% CI" %in% colnames(result_05$results)) expect_true("5% CI" %in% colnames(result_10$results)) expect_true("95% CI" %in% colnames(result_10$results)) }) test_that("congruence_test works with different nboot values", { result_small <- congruence_test(test_model, nboot = 20, seed = 123) result_large <- congruence_test(test_model, nboot = 100, seed = 123) # Both should return valid results expect_true(all(is.finite(result_small$results[, "Original Est."]))) expect_true(all(is.finite(result_large$results[, "Original Est."]))) # Original estimates should be identical (same model) expect_equal(result_small$results[, "Original Est."], result_large$results[, "Original Est."]) }) test_that("congruence_test works with custom threshold", { result <- congruence_test(test_model, nboot = 50, seed = 123, threshold = 0.9) # Diff column should reflect threshold - original # Diff = threshold - abs(original) expect_true(all(is.finite(result$results[, "Diff"]))) }) # ============================================================================ # Input Validation Tests # ============================================================================ test_that("congruence_test rejects non-seminr model objects", { expect_warning( result <- congruence_test(list(not = "a_model"), nboot = 50), "only works with SEMinR models" ) expect_null(result) }) test_that("congruence_test rejects NULL input", { expect_warning( result <- congruence_test(NULL, nboot = 50), "only works with SEMinR models" ) expect_null(result) }) test_that("congruence_test rejects data frame input", { expect_warning( result <- congruence_test(data.frame(x = 1:10), nboot = 50), "only works with SEMinR models" ) expect_null(result) }) # ============================================================================ # Output Value Tests # ============================================================================ test_that("congruence_test original estimates are bounded", { result <- congruence_test(test_model, nboot = 50, seed = 123) # Congruence coefficients should be between -1 and 1 expect_true(all(result$results[, "Original Est."] >= -1)) expect_true(all(result$results[, "Original Est."] <= 1)) }) test_that("congruence_test bootstrap SD is positive", { result <- congruence_test(test_model, nboot = 50, seed = 123) expect_true(all(result$results[, "Bootstrap SD"] >= 0)) }) test_that("congruence_test confidence intervals are ordered correctly", { result <- congruence_test(test_model, nboot = 100, seed = 123, alpha = 0.05) lower_ci <- result$results[, "2.5% CI"] upper_ci <- result$results[, "97.5% CI"] # Lower CI should be less than or equal to upper CI expect_true(all(lower_ci <= upper_ci)) })