tests/testthat/test-quick_ttest.R

#===============================================================================
# Test: quick_ttest()
# File: test-quick_ttest.R
# Description: Unit tests for the quick_ttest() function
#===============================================================================

#------------------------------------------------------------------------------
# Setup: Create test data
#------------------------------------------------------------------------------

# Set seed for reproducibility
set.seed(123)

# Independent samples test data (normal distribution)
test_data_normal <- data.frame(
  group = rep(c("Control", "Treatment"), each = 25),
  value = c(rnorm(25, mean = 10, sd = 2), rnorm(25, mean = 12, sd = 2)),
  stringsAsFactors = FALSE
)

# Paired samples test data
test_data_paired <- data.frame(
  patient = rep(1:20, 2),
  timepoint = rep(c("Before", "After"), each = 20),
  score = c(rnorm(20, mean = 50, sd = 10), rnorm(20, mean = 55, sd = 10)),
  stringsAsFactors = FALSE
)

# Skewed data (for non-parametric test)
test_data_skewed <- data.frame(
  group = rep(c("A", "B"), each = 20),
  value = c(rexp(20, rate = 0.5), rexp(20, rate = 1)),
  stringsAsFactors = FALSE
)

# Small sample data
test_data_small <- data.frame(
  group = rep(c("X", "Y"), each = 5),
  value = c(rnorm(5, 10, 2), rnorm(5, 12, 2)),
  stringsAsFactors = FALSE
)

# Data with NA values
test_data_na <- test_data_normal
test_data_na$value[1:3] <- NA

#------------------------------------------------------------------------------
# Basic Functionality Tests
#------------------------------------------------------------------------------

test_that("quick_ttest() creates a quick_ttest_result object", {
  result <- quick_ttest(test_data_normal,
                        group = group,
                        value = value,
                        verbose = FALSE)
  expect_s3_class(result, "quick_ttest_result")
})

test_that("quick_ttest() performs independent samples t-test", {
  result <- quick_ttest(test_data_normal,
                        group = group,
                        value = value,
                        method = "t.test",
                        verbose = FALSE)
  expect_s3_class(result$test_result, "htest")
  expect_equal(result$method_used, "t.test")
  expect_true("p.value" %in% names(result$test_result))
})

test_that("quick_ttest() performs paired t-test", {
  result <- quick_ttest(test_data_paired,
                        group = timepoint,
                        value = score,
                        paired = TRUE,
                        id = patient,
                        method = "t.test",
                        verbose = FALSE)
  expect_s3_class(result$test_result, "htest")
  expect_equal(result$method_used, "t.test")
  expect_true(result$parameters$paired)
})

test_that("quick_ttest() performs Wilcoxon test", {
  result <- quick_ttest(test_data_skewed,
                        group = group,
                        value = value,
                        method = "wilcox.test",
                        verbose = FALSE)
  expect_s3_class(result$test_result, "htest")
  expect_equal(result$method_used, "wilcox.test")
})

test_that("quick_ttest() auto-selects appropriate method", {
  # Normal data should select t-test
  result_normal <- quick_ttest(test_data_normal,
                                group = group,
                                value = value,
                                method = "auto",
                                verbose = FALSE)
  expect_equal(result_normal$method_used, "t.test")
})

test_that("quick_ttest() creates ggplot object", {
  result <- quick_ttest(test_data_normal,
                        group = group,
                        value = value,
                        verbose = FALSE)
  expect_s3_class(result$plot, "ggplot")
})

#------------------------------------------------------------------------------
# Parameter Validation Tests
#------------------------------------------------------------------------------

test_that("quick_ttest() validates data parameter", {
  expect_error(quick_ttest(NULL, group = group, value = value),
               "`data` must be a data frame")
  expect_error(quick_ttest(list(a = 1), group = group, value = value),
               "`data` must be a data frame")
})

test_that("quick_ttest() validates paired parameter", {
  expect_error(quick_ttest(test_data_normal, group = group, value = value,
                          paired = "yes"),
               "`paired` must be TRUE or FALSE")
  expect_error(quick_ttest(test_data_normal, group = group, value = value,
                          paired = c(TRUE, FALSE)),
               "`paired` must be TRUE or FALSE")
})

test_that("quick_ttest() requires id when paired = TRUE", {
  expect_error(quick_ttest(test_data_paired,
                          group = timepoint,
                          value = score,
                          paired = TRUE,
                          verbose = FALSE),
               "`id` must be specified when `paired` is TRUE")
})

test_that("quick_ttest() validates conf.level parameter", {
  expect_error(quick_ttest(test_data_normal, group = group, value = value,
                          conf.level = 1.5),
               "`conf.level` must be between 0 and 1")
  expect_error(quick_ttest(test_data_normal, group = group, value = value,
                          conf.level = -0.5),
               "`conf.level` must be between 0 and 1")
})

test_that("quick_ttest() validates column names", {
  expect_error(quick_ttest(test_data_normal,
                          group = nonexistent,
                          value = value,
                          verbose = FALSE),
               "not found")
  expect_error(quick_ttest(test_data_normal,
                          group = group,
                          value = nonexistent,
                          verbose = FALSE),
               "not found")
})

test_that("quick_ttest() validates value is numeric", {
  bad_data <- test_data_normal
  bad_data$value <- as.character(bad_data$value)
  expect_error(quick_ttest(bad_data, group = group, value = value,
                          verbose = FALSE),
               "must be numeric")
})

test_that("quick_ttest() requires exactly 2 groups", {
  multi_group_data <- data.frame(
    group = rep(c("A", "B", "C"), each = 10),
    value = rnorm(30)
  )
  expect_error(quick_ttest(multi_group_data, group = group, value = value,
                          verbose = FALSE),
               "requires exactly 2 groups")
})

#------------------------------------------------------------------------------
# Paired Data Validation Tests
#------------------------------------------------------------------------------

test_that("quick_ttest() validates paired IDs are in both groups", {
  bad_paired_data <- test_data_paired
  bad_paired_data <- bad_paired_data[-1, ]  # Remove one observation

  expect_error(quick_ttest(bad_paired_data,
                          group = timepoint,
                          value = score,
                          paired = TRUE,
                          id = patient,
                          verbose = FALSE),
               "must appear in both groups")
})

test_that("quick_ttest() validates paired IDs are not duplicated", {
  bad_paired_data <- test_data_paired
  bad_paired_data <- rbind(bad_paired_data, bad_paired_data[1, ])  # Duplicate one row

  expect_error(quick_ttest(bad_paired_data,
                          group = timepoint,
                          value = score,
                          paired = TRUE,
                          id = patient,
                          verbose = FALSE),
               "exactly once per group")
})

test_that("quick_ttest() accepts different column names as id", {
  paired_data_alt <- test_data_paired
  names(paired_data_alt)[1] <- "subject_id"

  result <- quick_ttest(paired_data_alt,
                        group = timepoint,
                        value = score,
                        paired = TRUE,
                        id = subject_id,
                        verbose = FALSE)
  expect_s3_class(result, "quick_ttest_result")
})

#------------------------------------------------------------------------------
# Statistical Tests Validation
#------------------------------------------------------------------------------

test_that("quick_ttest() performs normality checks for independent samples", {
  result <- quick_ttest(test_data_normal,
                        group = group,
                        value = value,
                        method = "auto",
                        verbose = FALSE)
  expect_true(!is.null(result$normality_tests))
  expect_true("recommendation" %in% names(result$normality_tests))
})

test_that("quick_ttest() checks normality of differences for paired samples", {
  result <- quick_ttest(test_data_paired,
                        group = timepoint,
                        value = score,
                        paired = TRUE,
                        id = patient,
                        method = "auto",
                        verbose = FALSE)
  expect_true(!is.null(result$normality_tests))
  expect_true(result$normality_tests$paired)
})

test_that("quick_ttest() checks variance equality for independent t-test", {
  result <- quick_ttest(test_data_normal,
                        group = group,
                        value = value,
                        method = "t.test",
                        var.equal = NULL,
                        verbose = FALSE)
  # Should have variance test result (or default to FALSE if car not available)
  expect_true(is.logical(result$parameters$var.equal) ||
              !is.null(result$variance_test))
})

test_that("quick_ttest() handles paired tests appropriately", {
  result <- quick_ttest(test_data_paired,
                        group = timepoint,
                        value = score,
                        paired = TRUE,
                        id = patient,
                        method = "t.test",
                        verbose = FALSE)
  # For paired tests, function should work correctly
  expect_true(result$parameters$paired)
  expect_s3_class(result$test_result, "htest")
})

test_that("quick_ttest() respects var.equal parameter", {
  result_equal <- quick_ttest(test_data_normal,
                              group = group,
                              value = value,
                              method = "t.test",
                              var.equal = TRUE,
                              verbose = FALSE)
  expect_true(result_equal$parameters$var.equal)

  result_unequal <- quick_ttest(test_data_normal,
                                group = group,
                                value = value,
                                method = "t.test",
                                var.equal = FALSE,
                                verbose = FALSE)
  expect_false(result_unequal$parameters$var.equal)
})

#------------------------------------------------------------------------------
# Plot Customization Tests
#------------------------------------------------------------------------------

test_that("quick_ttest() supports different plot types", {
  result_box <- quick_ttest(test_data_normal, group = group, value = value,
                            plot_type = "boxplot", verbose = FALSE)
  expect_s3_class(result_box$plot, "ggplot")

  result_violin <- quick_ttest(test_data_normal, group = group, value = value,
                               plot_type = "violin", verbose = FALSE)
  expect_s3_class(result_violin$plot, "ggplot")

  result_both <- quick_ttest(test_data_normal, group = group, value = value,
                             plot_type = "both", verbose = FALSE)
  expect_s3_class(result_both$plot, "ggplot")
})

test_that("quick_ttest() supports jitter customization", {
  result_no_jitter <- quick_ttest(test_data_normal, group = group, value = value,
                                  add_jitter = FALSE, verbose = FALSE)
  expect_s3_class(result_no_jitter$plot, "ggplot")

  result_custom <- quick_ttest(test_data_normal, group = group, value = value,
                               add_jitter = TRUE, point_size = 3,
                               point_alpha = 0.8, verbose = FALSE)
  expect_s3_class(result_custom$plot, "ggplot")
})

test_that("quick_ttest() supports p-value label formats", {
  result_stars <- quick_ttest(test_data_normal, group = group, value = value,
                              p_label = "p.signif", verbose = FALSE)
  expect_s3_class(result_stars$plot, "ggplot")

  result_numeric <- quick_ttest(test_data_normal, group = group, value = value,
                                p_label = "p.format", verbose = FALSE)
  expect_s3_class(result_numeric$plot, "ggplot")
})

test_that("quick_ttest() supports hiding p-value", {
  result <- quick_ttest(test_data_normal, group = group, value = value,
                        show_p_value = FALSE, verbose = FALSE)
  expect_s3_class(result$plot, "ggplot")
})

test_that("quick_ttest() accepts palette parameter", {
  result <- quick_ttest(test_data_normal, group = group, value = value,
                        palette = "qual_bold", verbose = FALSE)
  expect_s3_class(result$plot, "ggplot")
})

test_that("quick_ttest() accepts NULL palette", {
  result <- quick_ttest(test_data_normal, group = group, value = value,
                        palette = NULL, verbose = FALSE)
  expect_s3_class(result$plot, "ggplot")
})

#------------------------------------------------------------------------------
# Return Object Structure Tests
#------------------------------------------------------------------------------

test_that("quick_ttest() returns object with required components", {
  result <- quick_ttest(test_data_normal, group = group, value = value,
                        verbose = FALSE)

  expect_true("plot" %in% names(result))
  expect_true("test_result" %in% names(result))
  expect_true("method_used" %in% names(result))
  expect_true("normality_tests" %in% names(result))
  expect_true("descriptive_stats" %in% names(result))
  expect_true("parameters" %in% names(result))
  expect_true("timestamp" %in% names(result))
})

test_that("quick_ttest() result contains descriptive statistics", {
  result <- quick_ttest(test_data_normal, group = group, value = value,
                        verbose = FALSE)

  expect_s3_class(result$descriptive_stats, "data.frame")
  expect_true("n" %in% names(result$descriptive_stats))
  expect_true("mean" %in% names(result$descriptive_stats))
  expect_true("sd" %in% names(result$descriptive_stats))
})

test_that("quick_ttest() stores parameters correctly", {
  result <- quick_ttest(test_data_normal,
                        group = group,
                        value = value,
                        paired = FALSE,
                        alternative = "two.sided",
                        conf.level = 0.95,
                        verbose = FALSE)

  expect_false(result$parameters$paired)
  expect_equal(result$parameters$alternative, "two.sided")
  expect_equal(result$parameters$conf.level, 0.95)
})

#------------------------------------------------------------------------------
# Edge Cases and Special Scenarios
#------------------------------------------------------------------------------

test_that("quick_ttest() handles small samples", {
  result <- quick_ttest(test_data_small, group = group, value = value,
                        verbose = FALSE)
  expect_s3_class(result, "quick_ttest_result")
})

test_that("quick_ttest() handles data with NA values", {
  # Function should handle NA values (with or without warning depending on verbose)
  result <- quick_ttest(test_data_na, group = group, value = value,
                       verbose = FALSE)
  expect_s3_class(result, "quick_ttest_result")
  # Check that rows with NA were removed
  expect_true(nrow(result$descriptive_stats) == 2)
})

test_that("quick_ttest() handles one-sided tests", {
  result_greater <- quick_ttest(test_data_normal,
                                group = group,
                                value = value,
                                alternative = "greater",
                                verbose = FALSE)
  expect_equal(result_greater$parameters$alternative, "greater")

  result_less <- quick_ttest(test_data_normal,
                             group = group,
                             value = value,
                             alternative = "less",
                             verbose = FALSE)
  expect_equal(result_less$parameters$alternative, "less")
})

test_that("quick_ttest() handles different confidence levels", {
  result_90 <- quick_ttest(test_data_normal,
                           group = group,
                           value = value,
                           conf.level = 0.90,
                           verbose = FALSE)
  expect_equal(result_90$parameters$conf.level, 0.90)

  result_99 <- quick_ttest(test_data_normal,
                           group = group,
                           value = value,
                           conf.level = 0.99,
                           verbose = FALSE)
  expect_equal(result_99$parameters$conf.level, 0.99)
})

test_that("quick_ttest() handles unbalanced sample sizes", {
  unbalanced_data <- data.frame(
    group = c(rep("A", 10), rep("B", 30)),
    value = rnorm(40)
  )
  # Function should handle unbalanced sample sizes
  result <- quick_ttest(unbalanced_data, group = group, value = value,
                       verbose = FALSE)
  expect_s3_class(result, "quick_ttest_result")
  # Check descriptive stats show different sample sizes
  expect_true(result$descriptive_stats$n[1] != result$descriptive_stats$n[2])
})

test_that("quick_ttest() handles groups with equal variances", {
  equal_var_data <- data.frame(
    group = rep(c("A", "B"), each = 20),
    value = c(rnorm(20, 10, 2), rnorm(20, 12, 2))
  )
  result <- quick_ttest(equal_var_data,
                        group = group,
                        value = value,
                        var.equal = NULL,
                        verbose = FALSE)
  expect_s3_class(result, "quick_ttest_result")
})

#------------------------------------------------------------------------------
# S3 Methods Tests
#------------------------------------------------------------------------------

test_that("print.quick_ttest_result works", {
  result <- quick_ttest(test_data_normal, group = group, value = value,
                        verbose = FALSE)
  # print method displays plot and descriptive stats
  expect_output(print(result), "Method:|group|value")
})

test_that("summary.quick_ttest_result works", {
  result <- quick_ttest(test_data_normal, group = group, value = value,
                        verbose = FALSE)
  # summary should produce output - just check it runs without error
  expect_output(summary(result))
})

test_that("quick_ttest_result contains plot", {
  result <- quick_ttest(test_data_normal, group = group, value = value,
                        verbose = FALSE)
  # Result should contain a ggplot object
  expect_s3_class(result$plot, "ggplot")
})

#------------------------------------------------------------------------------
# Verbose Mode Tests
#------------------------------------------------------------------------------

test_that("quick_ttest() prints messages when verbose = TRUE", {
  # Function should produce diagnostic messages when verbose = TRUE
  # Using expect_message to catch cli output
  result <- quick_ttest(test_data_normal, group = group, value = value,
                       verbose = TRUE)
  # Just verify the result is created - verbose messages are visible in test output
  expect_s3_class(result, "quick_ttest_result")
})

test_that("quick_ttest() minimizes output when verbose = FALSE", {
  # verbose = FALSE should minimize output (palette messages may still appear)
  result <- quick_ttest(test_data_normal, group = group, value = value,
                       verbose = FALSE)
  # Just check the result is created successfully
  expect_s3_class(result, "quick_ttest_result")
})

#------------------------------------------------------------------------------
# Integration Tests
#------------------------------------------------------------------------------

test_that("quick_ttest() end-to-end workflow for independent samples", {
  result <- quick_ttest(
    data = test_data_normal,
    group = group,
    value = value,
    method = "auto",
    plot_type = "boxplot",
    add_jitter = TRUE,
    show_p_value = TRUE,
    p_label = "p.signif",
    palette = "qual_vivid",
    verbose = FALSE
  )

  expect_s3_class(result, "quick_ttest_result")
  expect_s3_class(result$plot, "ggplot")
  expect_s3_class(result$test_result, "htest")
  expect_true(result$test_result$p.value >= 0 && result$test_result$p.value <= 1)
})

test_that("quick_ttest() end-to-end workflow for paired samples", {
  result <- quick_ttest(
    data = test_data_paired,
    group = timepoint,
    value = score,
    paired = TRUE,
    id = patient,
    method = "auto",
    plot_type = "violin",
    show_p_value = TRUE,
    verbose = FALSE
  )

  expect_s3_class(result, "quick_ttest_result")
  expect_s3_class(result$plot, "ggplot")
  expect_s3_class(result$test_result, "htest")
  expect_true(result$parameters$paired)
  expect_true(result$test_result$p.value >= 0 && result$test_result$p.value <= 1)
})

#===============================================================================
# End: test-quick_ttest.R
#===============================================================================

Try the evanverse package in your browser

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

evanverse documentation built on March 10, 2026, 5:07 p.m.