R-CMD-check / check (push) Successful in 3m5s
Rewrites expenditure/revenue classification off item-code first-letter
prefixes and onto summary_categories membership (F-018: prefix Y spans
revenue, expenditure, and balance codes), and exposes
expenditure_concept = c("primary", "direct", "total") with primary as
the new default:
primary = operations + capital + assistance
direct = primary + interest + insurance_benefits (Census Direct)
total = direct + intergovernmental (M/L/Q via ig views)
- inst/sql: flow views (20-25) select by crosswalk membership;
summary_categories moves to 11- so it registers before them (DuckDB
binds view sources eagerly). The IG leg gains Q11/Q12/Q18 state
school-system payments (F-017).
- R: one subtype scope per verb call drives the verb SQL, the
harmonization exclusion count, and the complete = TRUE grid;
flow_prefixes survives only to scope recipe suggestions.
cog_geographic_rollup/cog_peer_compare accept primary|direct, still
refuse total, and now actually pass the concept through.
- Balance codes can never reach a spending or revenue result
(uscogdata#25), asserted at both view and verb level.
- Deletes the #11 skip; per the 2026-07-30 owner ruling the F-018 Y01
proof is asserted against the crosswalk, not the default
cog_revenue() call (which stays General Revenue pending #12).
Suite: 696 pass / 0 fail / 1 skip (#12, expected).
Closes #11
121 lines
4.2 KiB
R
121 lines
4.2 KiB
R
test_that("cog_explain prints verb header and target", {
|
|
skip_if_no_corpus()
|
|
r <- cog_spending("121011212191", 2020L, "Corrections")
|
|
# cli writes to stderr; capture both stdout and message streams.
|
|
txt <- paste(c(
|
|
capture.output(cog_explain(r)),
|
|
capture.output(cog_explain(r), type = "message")
|
|
), collapse = "\n")
|
|
expect_true(grepl("cog_spending", txt))
|
|
expect_true(grepl("Corrections", txt))
|
|
expect_true(grepl("121011212191", txt))
|
|
})
|
|
|
|
test_that("cog_explain format='list' returns structured provenance", {
|
|
skip_if_no_corpus()
|
|
r <- cog_spending("121011212191", 2020L, "Corrections")
|
|
prov <- cog_explain(r, format = "list")
|
|
expect_identical(prov, attr(r, "provenance"))
|
|
})
|
|
|
|
test_that("cog_explain returns result invisibly for chaining", {
|
|
skip_if_no_corpus()
|
|
r <- cog_spending("121011212191", 2020L, "Corrections")
|
|
res <- withVisible(cog_explain(r))
|
|
expect_false(res$visible)
|
|
expect_identical(res$value, r)
|
|
})
|
|
|
|
test_that("cog_explain errors on non-verb input", {
|
|
df <- tibble::tibble(a = 1)
|
|
expect_error(cog_explain(df), "provenance")
|
|
})
|
|
|
|
test_that("cog_explain prints basis + harmonization block", {
|
|
skip_if_no_corpus()
|
|
r <- cog_spending("121011212191", 2020L, "Corrections")
|
|
txt <- paste(c(
|
|
capture.output(cog_explain(r)),
|
|
capture.output(cog_explain(r), type = "message")
|
|
), collapse = "\n")
|
|
expect_true(grepl("Basis: harmonized", txt))
|
|
expect_true(grepl("Harmonization", txt))
|
|
expect_true(grepl("Excluded 0 row", txt))
|
|
})
|
|
|
|
test_that("cog_explain prints a Recipe section for recipe = results", {
|
|
skip_if_no_corpus()
|
|
r <- cog_spending("121011212191", c(2011L, 2012L), recipe = "corrections_combined")
|
|
txt <- paste(c(
|
|
capture.output(cog_explain(r)),
|
|
capture.output(cog_explain(r), type = "message")
|
|
), collapse = "\n")
|
|
expect_true(grepl("Recipe", txt))
|
|
expect_true(grepl("corrections_combined", txt))
|
|
expect_true(grepl("E04", txt))
|
|
expect_true(grepl("E05", txt))
|
|
})
|
|
|
|
test_that("cog_explain prints a Suggestions section when the provenance has one", {
|
|
skip_if_no_corpus()
|
|
r <- suppressMessages(
|
|
cog_spending("121011212191", c(2011L, 2012L), category = "Corrections")
|
|
)
|
|
txt <- paste(c(
|
|
capture.output(cog_explain(r)),
|
|
capture.output(cog_explain(r), type = "message")
|
|
), collapse = "\n")
|
|
expect_true(grepl("Suggestions", txt))
|
|
expect_true(grepl("corrections_combined", txt))
|
|
expect_true(grepl("re-run with recipe", txt))
|
|
})
|
|
|
|
test_that("cog_explain prints the expenditure concept (I1)", {
|
|
skip_if_no_corpus()
|
|
d <- cog_spending("010000226085", years = 2019, category = "Police")
|
|
t <- cog_spending("010000226085", years = 2019, category = "Police",
|
|
expenditure_concept = "total")
|
|
txt_d <- paste(c(
|
|
capture.output(cog_explain(d)),
|
|
capture.output(cog_explain(d), type = "message")
|
|
), collapse = "\n")
|
|
txt_t <- paste(c(
|
|
capture.output(cog_explain(t)),
|
|
capture.output(cog_explain(t), type = "message")
|
|
), collapse = "\n")
|
|
expect_true(grepl("Concept: primary", txt_d))
|
|
expect_true(grepl("Concept: total", txt_t))
|
|
})
|
|
|
|
test_that("cog_explain surfaces the C1(b) direct-suppressed flag as a warning", {
|
|
skip_if_no_corpus()
|
|
t <- suppressMessages(cog_spending(
|
|
"010000226085", years = 2011, category = "Corrections",
|
|
expenditure_concept = "total"
|
|
))
|
|
expect_true(attr(t, "provenance")$expenditure_concept_direct_suppressed)
|
|
txt <- paste(c(
|
|
capture.output(cog_explain(t)),
|
|
capture.output(cog_explain(t), type = "message")
|
|
), collapse = "\n")
|
|
expect_true(grepl("Direct leg unavailable", txt))
|
|
})
|
|
|
|
test_that("cog_explain prints denominator + popyear_range + counts", {
|
|
skip_if_no_corpus()
|
|
with_fixture_corpus({
|
|
r <- cog_spending("121011212191", years = 2019:2020,
|
|
category = "Police", per_capita = TRUE)
|
|
out <- paste(c(
|
|
capture.output(cog_explain(r)),
|
|
capture.output(cog_explain(r), type = "message")
|
|
), collapse = "\n")
|
|
expect_true(grepl("Census F-33", out))
|
|
expect_true(grepl("popyear", out, ignore.case = TRUE))
|
|
expect_true(grepl("census_f33", out))
|
|
# popyear_range should render as 4-digit calendar years, not raw 2-digit
|
|
expect_true(grepl("2019-2020", out))
|
|
expect_false(grepl("popyear range: 19-20", out, fixed = TRUE))
|
|
})
|
|
})
|