# test-7-ovb-minimal-reporting.R # Tests for ovb_minimal_reporting and internal table functions # setup ------------------------------------------------------------------- data("card") y <- card$lwage d <- card$educ z <- card$nearc4 x <- model.matrix(~ exper + expersq + black + south + smsa + reg661 + reg662 + reg663 + reg664 + reg665 + reg666 + reg667 + reg668 + smsa66, data = card) card.fit <- iv_fit(y, d, z, x) card.sens <- sensemakr(card.fit, benchmark_covariates = c("black", "smsa")) # also create a sensemakr object without benchmarks (no bounds) card.sens.nobounds <- sensemakr(card.fit) # format dispatch --------------------------------------------------------- test_that("ovb_minimal_reporting default format is latex", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE) expect_true(grepl("\\\\begin\\{table\\}", out)) expect_true(grepl("\\\\end\\{table\\}", out)) }) test_that("ovb_minimal_reporting dispatches to html format", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE, format = "html") expect_true(grepl("", out, fixed = TRUE)) expect_true(grepl("
", out, fixed = TRUE)) # html format uses mathjax notation expect_true(grepl("$XRV_{", out, fixed = TRUE)) }) test_that("ovb_minimal_reporting dispatches to pure_html format", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE, format = "pure_html") expect_true(grepl("", out, fixed = TRUE)) # pure_html uses tags, not mathjax expect_true(grepl("", out, fixed = TRUE)) expect_true(grepl("α", out, fixed = TRUE)) }) # LaTeX output content ---------------------------------------------------- test_that("latex table contains key structural elements", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE) expect_true(grepl("\\\\begin\\{tabular\\}", out)) expect_true(grepl("\\\\hline", out)) expect_true(grepl("XRV_\\{", out)) expect_true(grepl("RV_\\{", out)) expect_true(grepl("\\\\alpha", out)) expect_true(grepl("Est\\.", out)) expect_true(grepl("Lower CI", out)) expect_true(grepl("Upper CI", out)) expect_true(grepl("t-value", out)) }) test_that("latex table contains numeric results", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE) # estimate should be 0.132 expect_true(grepl("0\\.132", out)) # df should be 2994 expect_true(grepl("2994", out)) }) # custom labels ----------------------------------------------------------- test_that("custom labels are used in latex output", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE, outcome_label = "lwage", treatment_label = "educ") expect_true(grepl("lwage", out, fixed = TRUE)) expect_true(grepl("educ", out, fixed = TRUE)) }) test_that("custom labels are used in html output", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE, format = "html", outcome_label = "lwage", treatment_label = "educ") expect_true(grepl("lwage", out, fixed = TRUE)) expect_true(grepl("educ", out, fixed = TRUE)) }) test_that("custom labels are used in pure_html output", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE, format = "pure_html", outcome_label = "lwage", treatment_label = "educ") expect_true(grepl("lwage", out, fixed = TRUE)) expect_true(grepl("educ", out, fixed = TRUE)) }) # default labels from iv_fit --------------------------------------------- test_that("default labels come from iv_fit variable names", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE) # the y_name is "y" and d_name is "d" from deparse(substitute()) # just check a label appears (not NULL) expect_true(is.character(out)) expect_true(nchar(out) > 100) }) # verbose flag ------------------------------------------------------------ test_that("verbose = TRUE prints output", { expect_output(ovb_minimal_reporting(card.sens, verbose = TRUE)) }) test_that("verbose = FALSE does not print", { expect_silent(out <- ovb_minimal_reporting(card.sens, verbose = FALSE)) expect_true(is.character(out)) }) test_that("verbose = FALSE for html does not print", { expect_silent(out <- ovb_minimal_reporting(card.sens, verbose = FALSE, format = "html")) expect_true(is.character(out)) }) test_that("verbose = FALSE for pure_html does not print", { expect_silent(out <- ovb_minimal_reporting(card.sens, verbose = FALSE, format = "pure_html")) expect_true(is.character(out)) }) # invisible return -------------------------------------------------------- test_that("return value is invisible character string", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE) expect_type(out, "character") expect_length(out, 1) }) # bounds in footnote ------------------------------------------------------ test_that("latex footnote contains bound info when benchmarks present", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE) expect_true(grepl("Bound", out, fixed = TRUE)) expect_true(grepl("1x black", out, fixed = TRUE)) expect_true(grepl("R\\^2_\\{Z", out)) expect_true(grepl("R\\^2_\\{Y\\(0\\)", out)) }) test_that("html footnote contains bound info", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE, format = "html") expect_true(grepl("Bound", out, fixed = TRUE)) expect_true(grepl("1x black", out, fixed = TRUE)) }) test_that("pure_html footnote contains bound info", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE, format = "pure_html") expect_true(grepl("Bound", out, fixed = TRUE)) expect_true(grepl("1x black", out, fixed = TRUE)) expect_true(grepl("R2", out, fixed = TRUE)) }) # no bounds case ---------------------------------------------------------- test_that("latex works without benchmarks (no bounds)", { out <- ovb_minimal_reporting(card.sens.nobounds, verbose = FALSE) expect_true(is.character(out)) expect_true(grepl("\\\\begin\\{table\\}", out)) # should NOT have bound info expect_false(grepl("Bound", out, fixed = TRUE)) }) test_that("html works without benchmarks (no bounds)", { out <- ovb_minimal_reporting(card.sens.nobounds, verbose = FALSE, format = "html") expect_true(is.character(out)) expect_false(grepl("Bound", out, fixed = TRUE)) }) test_that("pure_html works without benchmarks (no bounds)", { out <- ovb_minimal_reporting(card.sens.nobounds, verbose = FALSE, format = "pure_html") expect_true(is.character(out)) expect_false(grepl("Bound", out, fixed = TRUE)) }) # .escape_latex ----------------------------------------------------------- test_that(".escape_latex escapes dollar signs", { escaped <- iv.sensemakr:::.escape_latex("card$lwage") expect_true(grepl("\\\\\\$", escaped)) expect_equal(escaped, "card\\$lwage") }) test_that(".escape_latex escapes multiple special characters", { escaped <- iv.sensemakr:::.escape_latex("a$b%c&d#e_f{g}h") expect_true(grepl("\\\\\\$", escaped)) expect_true(grepl("\\\\%", escaped)) expect_true(grepl("\\\\&", escaped)) expect_true(grepl("\\\\#", escaped)) expect_true(grepl("\\\\_", escaped)) }) test_that(".escape_latex handles plain strings", { expect_equal(iv.sensemakr:::.escape_latex("educ"), "educ") expect_equal(iv.sensemakr:::.escape_latex("lwage"), "lwage") }) # caption and label ------------------------------------------------------- test_that("latex caption and label arguments work", { out <- ovb_minimal_reporting(card.sens, verbose = FALSE, caption = "IV sensitivity table", label = "tab:iv") expect_true(grepl("\\\\caption\\{IV sensitivity table\\}", out)) expect_true(grepl("\\\\label\\{tab:iv\\}", out)) }) # fallback to sensemakr --------------------------------------------------- test_that("ovb_minimal_reporting fallback works for sensemakr objects", { skip_if_not_installed("sensemakr") # create a regular OLS sensemakr object data("card") lm_fit <- lm(lwage ~ educ + exper + expersq + black + south + smsa, data = card) ols_sens <- sensemakr::sensemakr(lm_fit, treatment = "educ", benchmark_covariates = "black") out <- ovb_minimal_reporting(ols_sens, verbose = FALSE) expect_true(is.character(out)) # OLS table should have different structure (S.E. column, not Lower/Upper CI) expect_true(grepl("S\\.E\\.", out)) }) # digits ------------------------------------------------------------------ test_that("digits parameter controls precision", { out5 <- ovb_minimal_reporting(card.sens, verbose = FALSE, digits = 5) out2 <- ovb_minimal_reporting(card.sens, verbose = FALSE, digits = 2) # more digits -> longer string expect_true(nchar(out5) >= nchar(out2)) })