## ---- stress_test ---------------------------------------------------- test_that("stress_test gives maximal robustness for zero perturbation", { baseline <- c(1, 2, 3, 4, 5) out <- stress_test(baseline, list(identical = baseline)) expect_equal(out$robustness_index, 1) expect_equal(out$by_perturbation$identical$mean_abs_change, 0) expect_equal(out$by_perturbation$identical$rmse, 0) }) test_that("stress_test robustness_index decreases with larger perturbation", { set.seed(20) baseline <- rnorm(100, mean = 5, sd = 1) small <- baseline + rnorm(100, mean = 0.1, sd = 0.05) large <- baseline + rnorm(100, mean = 1.0, sd = 0.05) out_small <- stress_test(baseline, list(p = small)) out_large <- stress_test(baseline, list(p = large)) expect_gt(out_small$robustness_index, out_large$robustness_index) }) test_that("stress_test errors on mismatched perturbation length", { expect_error(stress_test(1:5, list(bad = 1:4))) }) ## ---- prompt_sensitivity -------------------------------------------- test_that("identical paraphrase outputs imply zero within-prompt variance", { scores <- list( version1 = c(1, 2, 3, 4), version2 = c(1, 2, 3, 4), version3 = c(1, 2, 3, 4) ) out <- prompt_sensitivity(scores) expect_equal(out$within_prompt_variance, 0) expect_true(is.na(out$sensitivity_ratio) || out$sensitivity_ratio == 0) }) test_that("prompt_sensitivity flags high within-prompt variance", { set.seed(21) # same underlying prompts but wildly different across paraphrases scores <- list( v1 = c(1, 2, 3, 4), v2 = c(4, 3, 2, 1), v3 = c(2, 4, 1, 3) ) out <- prompt_sensitivity(scores) expect_gt(out$within_prompt_variance, 0) }) test_that("prompt_sensitivity errors on unequal-length paraphrase groups", { expect_error(prompt_sensitivity(list(a = 1:4, b = 1:3)), "equal length") }) test_that("prompt_sensitivity warns and returns NA ratio when between variance is zero", { # every underlying prompt has the same mean across paraphrases -> zero between var scores <- list(v1 = c(1, 1, 1), v2 = c(2, 2, 2)) # row means are all 1.5 -> between-prompt variance zero expect_warning(out <- prompt_sensitivity(scores), "zero") expect_true(is.na(out$sensitivity_ratio)) }) ## ---- adversarial_stability ----------------------------------------- test_that("adversarial_stability reports zero flips when outputs are unchanged", { orig <- c("A", "B", "A", "C") adv <- c("A", "B", "A", "C") out <- adversarial_stability(orig, adv) expect_equal(out$flip_rate, 0) expect_equal(out$n, 4) }) test_that("adversarial_stability reports full flip rate when all change", { orig <- c("A", "B", "A", "C") adv <- c("B", "A", "C", "A") out <- adversarial_stability(orig, adv) expect_equal(out$flip_rate, 1) }) test_that("adversarial_stability accepts a custom flip function", { orig <- c(1.0, 2.0, 3.0) adv <- c(1.05, 2.5, 3.0) # flip only if difference exceeds 0.4 out <- adversarial_stability(orig, adv, flip_fn = function(a, b) abs(a - b) > 0.4) expect_equal(out$flip_rate, 1/3) }) test_that("adversarial_stability errors on mismatched lengths", { expect_error(adversarial_stability(1:3, 1:2)) }) ## ---- ai_robustness (wrapper) --------------------------------------- test_that("ai_robustness wraps stress_test with the robustness class", { baseline <- c(1, 2, 3, 4, 5) out <- ai_robustness(baseline, list(p = baseline + 0.1)) expect_s3_class(out, "aiEvalR_robustness") expect_true("robustness_index" %in% names(out)) })