test_that("scenarios stack runs", { sc <- sd_scenarios(agri_adoption_model(), list(base = list(), fast = list(q = 0.6)), stop = 10) expect_s3_class(sc, "sd_scenarios") expect_equal(nrow(sc), 22) s <- summary(sc, vars = "adopters") expect_gt(s$final[s$scenario == "fast"], s$final[s$scenario == "base"]) expect_error(plot(sc, "nope")) }) test_that("sensitivity analysis returns bands and SRC", { sa <- sd_sensitivity(agri_adoption_model(), ranges = list(p = c(0.01, 0.05), q = c(0.2, 0.6)), outputs = "adopters", n = 20, stop = 8, seed = 42) expect_s3_class(sa, "sd_sensitivity") expect_equal(nrow(sa$samples), 20) expect_equal(nrow(sa$src), 2) expect_true(all(sa$samples$p >= 0.01 & sa$samples$p <= 0.05)) expect_output(print(sa), "Standardised") expect_error(sd_sensitivity(agri_adoption_model(), list(zz = c(0, 1)), "adopters", n = 5)) }) test_that("fit statistics decompose MSE", { f <- sd_fit_stats(c(1, 2, 3, 4), c(1.5, 2.5, 3.5, 4.5)) expect_equal(f[["um"]], 1) expect_equal(f[["um"]] + f[["us"]] + f[["uc"]], 1) expect_equal(f[["rmse"]], 0.5) p <- sd_fit_stats(1:5, 1:5) expect_equal(p[["theil_u"]], 0) }) test_that("calibration recovers known parameters", { true <- sd_simulate(agri_adoption_model(p = 0.02, q = 0.5), stop = 15) obs <- data.frame(time = true$time, adopters = true$adopters) cal <- sd_calibrate(agri_adoption_model(), obs, params = c(p = 0.05, q = 0.3), lower = c(0.001, 0.01), upper = c(0.2, 1), stop = 15) expect_equal(unname(cal$estimates), c(0.02, 0.5), tolerance = 0.02) expect_output(print(cal), "Estimates") }) test_that("NPV discounting", { run <- data.frame(time = 0:2, v = c(100, 100, 100)) expect_equal(sd_npv(run, "v", 0), 200) expect_lt(sd_npv(run, "v", 0.1), 200) expect_error(sd_npv(run, "w", 0.1)) })