diff --git a/inst/extdata/fixture_corpus/data/canonical_fips_xwalk.parquet b/inst/extdata/fixture_corpus/data/canonical_fips_xwalk.parquet new file mode 100644 index 0000000..e6f7e0f Binary files /dev/null and b/inst/extdata/fixture_corpus/data/canonical_fips_xwalk.parquet differ diff --git a/inst/extdata/fixture_corpus/data/long/year=2019/part-0.parquet b/inst/extdata/fixture_corpus/data/long/year=2019/part-0.parquet new file mode 100644 index 0000000..4c83042 Binary files /dev/null and b/inst/extdata/fixture_corpus/data/long/year=2019/part-0.parquet differ diff --git a/inst/extdata/fixture_corpus/data/long/year=2020/part-0.parquet b/inst/extdata/fixture_corpus/data/long/year=2020/part-0.parquet new file mode 100644 index 0000000..8c9d674 Binary files /dev/null and b/inst/extdata/fixture_corpus/data/long/year=2020/part-0.parquet differ diff --git a/inst/extdata/fixture_corpus/data/summary_categories.parquet b/inst/extdata/fixture_corpus/data/summary_categories.parquet new file mode 100644 index 0000000..8003ca4 Binary files /dev/null and b/inst/extdata/fixture_corpus/data/summary_categories.parquet differ diff --git a/inst/extdata/fixture_corpus/manifest.json b/inst/extdata/fixture_corpus/manifest.json new file mode 100644 index 0000000..0c1ccf4 --- /dev/null +++ b/inst/extdata/fixture_corpus/manifest.json @@ -0,0 +1,86 @@ +{ + "schema_version": 3, + "built_at": "2026-04-27T16:43:46Z", + "pipeline_commit": "899af37", + "fixture_note": "Two-year (2019-2020) fixture for uscogdata tests. Full corpus available via USCOGDATA_URL.", + "data_vintage": { + "census_source_downloaded": "unknown", + "cpi_vintage": "FRED CPIAUCSL", + "acs_vintage": "ACS 2018-2022 5-year" + }, + "scope": { + "gov_types_included": [ + 0, + 1, + 2, + 3 + ], + "gov_types_excluded": [ + 4, + 5 + ], + "scope_note": "v0.1 covers state, county, city/municipality, and township governments. Special districts (type 4) and school districts (type 5) are excluded pending validation in a future cycle." + }, + "schema": { + "long_column_count": 24, + "long_columns": [ + "fips_state", + "type", + "fips_county", + "govid", + "gov_blank", + "gov_name", + "county_name", + "fips_state_code", + "fips_county_code", + "fips_place_code", + "population", + "popyear", + "enrollment", + "enrollyear", + "function_code", + "sch_level_code", + "fiscal_year_end", + "srvy_year", + "item_code", + "amt", + "srv_data", + "impute_flag", + "is_aggregate", + "canonical_govid" + ], + "data_dictionary": "docs/data_dictionary.md" + }, + "files": { + "long_partitions": [ + { + "year": 2019, + "path": "data/long/year=2019/part-0.parquet", + "sha256": "e1c9f426c6d7d3c51d06b3a652473b987b304836619c213f019cee4887714daa", + "row_count": 318139, + "size_bytes": 1424231 + }, + { + "year": 2020, + "path": "data/long/year=2020/part-0.parquet", + "sha256": "9b795853a848e8c955c80261b96b79630fc77394dcfb1a1ca288e2cd634053a3", + "row_count": 317500, + "size_bytes": 1427150 + } + ], + "metadata": [ + { + "path": "data/canonical_fips_xwalk.parquet", + "sha256": "86e53e04a35f6f90bb74bb1a273e053392afa782d6f518e3e3da9c976d47f7af", + "description": "canonical_fips_xwalk.parquet" + }, + { + "path": "data/summary_categories.parquet", + "sha256": "60045e22bc2723318fa2cb73f8e5038250dc54d24b3447c6750dfe29035335b8", + "description": "summary_categories.parquet" + } + ] + }, + "series_breaks_ref": "docs/series_breaks.md", + "reader_spec_ref": "docs/reader-specification.md" +} diff --git a/tests/testthat/helper-fixture.R b/tests/testthat/helper-fixture.R index f63d983..12b79d3 100644 --- a/tests/testthat/helper-fixture.R +++ b/tests/testthat/helper-fixture.R @@ -1,6 +1,28 @@ # tests/testthat/helper-fixture.R + +# Returns the path to the bundled fixture corpus (trailing slash for DuckDB globs). +fixture_corpus_path <- function() { + p <- system.file("extdata/fixture_corpus", package = "uscogdata") + if (nzchar(p)) paste0(p, "/") else "" +} + +# Skip a test if no corpus is reachable (bundled fixture or explicit remote URL). skip_if_no_corpus <- function() { - testthat::skip_if(Sys.getenv("USCOGDATA_FIXTURE_URL", "") == "" && - !file.exists("~/.cache/R/uscogdata/manifest.json"), - "No fixture corpus available") + p <- fixture_corpus_path() + has_fixture <- nzchar(p) && file.exists(sub("/$", "/manifest.json", p)) + has_remote <- nzchar(Sys.getenv("USCOGDATA_FIXTURE_URL", "")) + testthat::skip_if(!has_fixture && !has_remote, "No fixture corpus available") +} + +# Run a block against the fixture corpus with a clean session. +# Restores the previous URL and closes the DuckDB connection when done. +with_fixture_corpus <- function(code) { + old_url <- Sys.getenv("USCOGDATA_URL", unset = NA) + uscogdata:::cog_close() + Sys.setenv(USCOGDATA_URL = fixture_corpus_path()) + on.exit({ + uscogdata:::cog_close() + if (is.na(old_url)) Sys.unsetenv("USCOGDATA_URL") else Sys.setenv(USCOGDATA_URL = old_url) + }, add = TRUE) + force(code) } diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index b774389..a88f0b4 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -1,5 +1,13 @@ # tests/testthat/setup.R -# Point tests at a fixture corpus URL if provided. -if (Sys.getenv("USCOGDATA_FIXTURE_URL", "") != "") { - options(uscogdata.url = Sys.getenv("USCOGDATA_FIXTURE_URL")) -} +# Priority: bundled fixture > USCOGDATA_FIXTURE_URL env var > whatever is already set. +local({ + p <- system.file("extdata/fixture_corpus", package = "uscogdata") + if (nzchar(p) && file.exists(file.path(p, "manifest.json"))) { + Sys.setenv(USCOGDATA_URL = paste0(p, "/")) + } else if (nzchar(Sys.getenv("USCOGDATA_FIXTURE_URL", ""))) { + Sys.setenv(USCOGDATA_URL = Sys.getenv("USCOGDATA_FIXTURE_URL")) + } +}) + +# Reset DuckDB session between test files so each file starts clean. +withr::defer(uscogdata:::cog_close(), teardown_env()) diff --git a/tests/testthat/test-spending.R b/tests/testthat/test-spending.R index cf5b3f7..89cf731 100644 --- a/tests/testthat/test-spending.R +++ b/tests/testthat/test-spending.R @@ -34,11 +34,11 @@ test_that("cog_spending with per_capita adds per-capita nominal column", { test_that("cog_spending with adjust_to_year adds real column", { skip_if_no_corpus() - r <- cog_spending("101006006", 2015:2020, "Corrections", + r <- cog_spending("101006006", 2019:2020, "Corrections", adjust_to_year = 2022L) expect_true("amt_real" %in% names(r)) - r2015 <- dplyr::filter(r, year == 2015L) - expect_true(any(r2015$amt_nominal != r2015$amt_real)) + r2019 <- dplyr::filter(r, year == 2019L) + expect_true(any(r2019$amt_nominal != r2019$amt_real)) }) test_that("cog_spending with per_capita + adjust_to_year adds all columns", {