tests/testthat/test-medci.R

# Test file for medci() function

test_that("medci works with basic parameters", {
  # Simple test with known parameters
  result <- medci(mu.x = 0.3, mu.y = 0.4, se.x = 0.1, se.y = 0.1, type = "asymp")

  expect_type(result, "list")
  expect_named(result, c("95% CI", "Estimate", "SE"))
  expect_length(result$`95% CI`, 2)
  expect_true(result$`95% CI`[1] < result$`95% CI`[2])
})

test_that("medci handles all type options", {
  mu.x <- 0.3
  mu.y <- 0.4
  se.x <- 0.1
  se.y <- 0.1

  # Test each type
  result_dop <- medci(mu.x, mu.y, se.x, se.y, type = "dop")
  result_mc <- medci(mu.x, mu.y, se.x, se.y, type = "mc", n.mc = 1e4)
  result_asymp <- medci(mu.x, mu.y, se.x, se.y, type = "asymp")
  result_all <- medci(mu.x, mu.y, se.x, se.y, type = "all", n.mc = 1e4)

  expect_type(result_dop, "list")
  expect_type(result_mc, "list")
  expect_type(result_asymp, "list")
  expect_type(result_all, "list")

  # When type="all", should return nested list
  expect_length(result_all, 3)
  expect_named(result_all, c("Distribution of Product", "Monte Carlo", "Asymptotic Normal"))
})

test_that("medci respects alpha parameter", {
  result_95 <- medci(0.3, 0.4, 0.1, 0.1, alpha = 0.05, type = "asymp")
  result_99 <- medci(0.3, 0.4, 0.1, 0.1, alpha = 0.01, type = "asymp")

  expect_named(result_95, c("95% CI", "Estimate", "SE"))
  expect_named(result_99, c("99% CI", "Estimate", "SE"))

  # 99% CI should be wider than 95% CI
  width_95 <- diff(result_95$`95% CI`)
  width_99 <- diff(result_99$`99% CI`)
  expect_true(width_99 > width_95)
})

test_that("medci handles rho parameter correctly", {
  # Test with rho = 0 (independence)
  result_rho0 <- medci(0.3, 0.4, 0.1, 0.1, rho = 0, type = "asymp")

  # Test with positive correlation
  result_rho_pos <- medci(0.3, 0.4, 0.1, 0.1, rho = 0.3, type = "asymp")

  # Test with negative correlation
  result_rho_neg <- medci(0.3, 0.4, 0.1, 0.1, rho = -0.3, type = "asymp")

  expect_type(result_rho0, "list")
  expect_type(result_rho_pos, "list")
  expect_type(result_rho_neg, "list")

  # SE should differ with different rho values
  expect_false(result_rho0$SE == result_rho_pos$SE)
})

test_that("medci validates parameter bounds", {
  # Test invalid rho values
  expect_error(
    medci(0.3, 0.4, 0.1, 0.1, rho = 1.5),
    "rho"
  )

  expect_error(
    medci(0.3, 0.4, 0.1, 0.1, rho = -1.5),
    "rho"
  )

  # Test invalid alpha values
  expect_error(
    medci(0.3, 0.4, 0.1, 0.1, alpha = 0),
    "alpha"
  )

  expect_error(
    medci(0.3, 0.4, 0.1, 0.1, alpha = 1),
    "alpha"
  )

  expect_error(
    medci(0.3, 0.4, 0.1, 0.1, alpha = 1.5),
    "alpha"
  )
})

test_that("medci validates type parameter", {
  expect_error(
    medci(0.3, 0.4, 0.1, 0.1, type = "invalid"),
    "should be one of"
  )
})

test_that("medci computes correct point estimate", {
  mu.x <- 0.3
  mu.y <- 0.4
  se.x <- 0.1
  se.y <- 0.1
  rho <- 0

  result <- medci(mu.x, mu.y, se.x, se.y, rho = rho, type = "asymp")

  # Point estimate should be mu.x * mu.y + rho * se.x * se.y
  expected_estimate <- mu.x * mu.y + rho * se.x * se.y
  expect_equal(result$Estimate, expected_estimate)
})

test_that("medci computes correct SE with rho=0", {
  mu.x <- 0.3
  mu.y <- 0.4
  se.x <- 0.1
  se.y <- 0.1
  rho <- 0

  result <- medci(mu.x, mu.y, se.x, se.y, rho = rho, type = "asymp")

  # Craig (1936) formula with rho=0
  expected_se <- sqrt(
    se.y^2 * mu.x^2 +
    se.x^2 * mu.y^2 +
    se.x^2 * se.y^2
  )

  expect_equal(result$SE, expected_se, tolerance = 1e-10)
})

test_that("medci MC method returns MC.Error", {
  result <- medci(0.3, 0.4, 0.1, 0.1, type = "mc", n.mc = 1e4)

  expect_true("MC.Error" %in% names(result))
  expect_true(is.numeric(result$MC.Error))
  expect_true(result$MC.Error > 0)
})

test_that("medci handles n.mc parameter", {
  # Small n.mc should run faster but be less precise
  result_small <- medci(0.3, 0.4, 0.1, 0.1, type = "mc", n.mc = 1e3)
  result_large <- medci(0.3, 0.4, 0.1, 0.1, type = "mc", n.mc = 1e4)

  expect_type(result_small, "list")
  expect_type(result_large, "list")

  # Larger n.mc should have smaller MC.Error
  expect_true(result_large$MC.Error < result_small$MC.Error)
})

test_that("medci plot parameters don't cause errors", {
  # plot=TRUE should not cause errors (but we won't actually display)
  expect_no_error(
    medci(0.3, 0.4, 0.1, 0.1, type = "asymp", plot = FALSE)
  )

  # Note: We don't test plot=TRUE in automated tests to avoid graphics device issues
})

test_that("medci handles edge case: zero indirect effect", {
  # When mu.x = 0, indirect effect should be 0 (with rho=0)
  result <- medci(0, 0.4, 0.1, 0.1, rho = 0, type = "asymp")

  expect_equal(result$Estimate, 0)
  expect_true(result$`95% CI`[1] < 0)
  expect_true(result$`95% CI`[2] > 0)
})

test_that("medci handles negative coefficients", {
  # Negative a path, positive b path
  result1 <- medci(-0.3, 0.4, 0.1, 0.1, type = "asymp")
  expect_true(result1$Estimate < 0)

  # Positive a path, negative b path
  result2 <- medci(0.3, -0.4, 0.1, 0.1, type = "asymp")
  expect_true(result2$Estimate < 0)

  # Both negative
  result3 <- medci(-0.3, -0.4, 0.1, 0.1, type = "asymp")
  expect_true(result3$Estimate > 0)
})

test_that("medci MC and DOP methods give similar results", {
  set.seed(123)

  result_mc <- medci(0.3, 0.4, 0.1, 0.1, type = "mc", n.mc = 1e5)
  result_dop <- medci(0.3, 0.4, 0.1, 0.1, type = "dop")

  # Estimates should be identical
  expect_equal(result_mc$Estimate, result_dop$Estimate, tolerance = 0.01)

  # CIs should be similar (within reason given MC error)
  expect_equal(result_mc$`95% CI`[1], result_dop$`95% CI`[1], tolerance = 0.03)
  expect_equal(result_mc$`95% CI`[2], result_dop$`95% CI`[2], tolerance = 0.03)
})

Try the RMediation package in your browser

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

RMediation documentation built on Nov. 20, 2025, 5:06 p.m.