Skip to content

Commit c0f3b80

Browse files
authored
Merge pull request #115 from cmu-delphi/ds/testthat
refactor(epidatacall): remove `fetch_csv` and use `testthat` mocking
2 parents fc7eb55 + e8ae92a commit c0f3b80

File tree

5 files changed

+31
-168
lines changed

5 files changed

+31
-168
lines changed

DESCRIPTION

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ RoxygenNote: 7.2.3
3434
Suggests:
3535
dplyr,
3636
knitr,
37-
mockery,
38-
mockr,
3937
rmarkdown,
4038
testthat (>= 3.1.5),
4139
withr

NAMESPACE

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ S3method(print,covidcast_data_signal)
66
S3method(print,covidcast_data_source)
77
S3method(print,covidcast_epidata)
88
S3method(print,epidata_call)
9-
S3method(print,epidata_csv)
109
export("%>%")
1110
export(covid_hosp_facility)
1211
export(covid_hosp_facility_lookup)

R/epidatacall.R

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -195,72 +195,6 @@ fetch_classic <- function(epidata_call, fields = NULL, disable_data_frame_parsin
195195
return(response_content$epidata)
196196
}
197197

198-
#' Fetches the data and returns a tibble or an `epidata_csv`
199-
#'
200-
#' @param epidata_call an instance of `epidata_call`
201-
#' @param fields filter fields
202-
#' @param disable_date_parsing Boolean. Optionally, `TRUE` to disable parsing of
203-
#' columns we expect to be dates, keeping them as character columns instead.
204-
#' `FALSE` (the default) to parse these columns into `Date` vectors.
205-
#' @param disable_tibble_output Boolean. Optionally, `TRUE` to output a
206-
#' character vector with the `epidata_csv` class (which provides a custom
207-
#' `print` method). `FALSE` (the default) to output a tibble.
208-
#' @return
209-
#' - For `fetch_csv`: a tibble, or `epidata_csv` if requested with
210-
#' `disable_tibble_output = TRUE`
211-
#'
212-
#' @importFrom httr stop_for_status content
213-
#' @importFrom rlang abort
214-
fetch_csv <- function(epidata_call, fields = NULL, disable_date_parsing = FALSE, disable_tibble_output = FALSE) {
215-
stopifnot(inherits(epidata_call, "epidata_call"))
216-
stopifnot(is.null(fields) || is.character(fields))
217-
218-
if (epidata_call$only_supports_classic) {
219-
rlang::abort("This endpoint only supports the classic message format, due to a non-standard behavior. Use fetch_classic instead.",
220-
epidata_call = epidata_call,
221-
class = "only_supports_classic_format"
222-
)
223-
}
224-
225-
response <- request_impl(epidata_call, "csv", fields)
226-
response_content <- httr::content(response, "text", encoding = "UTF-8")
227-
class(response_content) <- c("epidata_csv", class(response_content))
228-
229-
if (disable_tibble_output) {
230-
return(response_content)
231-
}
232-
233-
meta <- epidata_call$meta
234-
fields_pred <- fields_to_predicate(fields)
235-
col_names <- c()
236-
col_types <- list()
237-
for (i in seq_len(length(meta))) {
238-
info <- meta[[i]]
239-
if (fields_pred(info$name)) {
240-
col_names <- c(col_names, info$name)
241-
col_types[info$name] <- info_to_type(info, disable_date_parsing)
242-
}
243-
}
244-
245-
csv_tibble <- if (length(col_names) > 0) {
246-
readr::read_csv(response_content, col_types = col_types)
247-
} else {
248-
readr::read_csv(response_content)
249-
}
250-
251-
if (!disable_date_parsing) {
252-
# parse weeks
253-
columns <- colnames(csv_tibble)
254-
for (i in seq_len(length(meta))) {
255-
info <- meta[[i]]
256-
if (info$name %in% columns && info$type == "epiweek") {
257-
csv_tibble[[info$name]] <- parse_api_week(csv_tibble[[info$name]])
258-
}
259-
}
260-
}
261-
csv_tibble
262-
}
263-
264198
fetch_debug <- function(epidata_call, format_type = "classic", fields = NULL) {
265199
response <- request_impl(epidata_call, format_type, fields)
266200
content <- httr::content(response, "text", encoding = "UTF-8")
@@ -334,37 +268,3 @@ request_impl <- function(epidata_call, format_type, fields = NULL) {
334268

335269
response
336270
}
337-
338-
#' @export
339-
print.epidata_csv <- function(x, ...) {
340-
char_limit <- getOption("epidata_csv__char_limit", default = 300L)
341-
cat(
342-
"# A epidata_csv object with", nchar(x), "characters; showing up to", char_limit,
343-
"characters below. To print the entire string, use `print(as.character(x))`:\n"
344-
)
345-
cat(substr(x, 1L, char_limit))
346-
if (nchar(x) > char_limit) {
347-
cat("[...]")
348-
}
349-
cat("\n")
350-
invisible(x)
351-
}
352-
353-
info_to_type <- function(info, disable_date_parsing = FALSE) {
354-
types <- list(
355-
date = if (disable_date_parsing) {
356-
readr::col_integer()
357-
} else {
358-
readr::col_date(format = "%Y%m%d")
359-
},
360-
epiweek = readr::col_integer(),
361-
bool = readr::col_logical(),
362-
text = readr::col_character(),
363-
int = readr::col_integer(),
364-
float = readr::col_double(),
365-
categorical = readr::col_factor(info$categories)
366-
)
367-
r <- types[info$type]
368-
stopifnot(!is.null(r))
369-
r
370-
}

man/fetch_csv.Rd

Lines changed: 0 additions & 35 deletions
This file was deleted.

tests/testthat/test-epidatacall.R

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
test_that("fetch_tbl", {
1+
test_that("fetch and fetch_tbl", {
22
epidata_call <- covidcast(
33
data_source = "jhu-csse",
44
signals = "confirmed_7dav_incidence_prop",
@@ -7,31 +7,21 @@ test_that("fetch_tbl", {
77
time_values = epirange("2020-06-01", "2020-08-01"),
88
geo_values = "ca,fl"
99
)
10-
# Generated with
11-
# epidata_call %>%
12-
# fetch_debug(format_type = "classic") %>%
13-
# readr::write_rds(testthat::test_path("data/test-classic.rds"))
14-
mockery::stub(fetch_classic, "httr::content", readRDS(testthat::test_path("data/test-classic.rds")))
15-
mockery::stub(fetch_tbl, "fetch_classic", fetch_classic)
16-
# Generated with
17-
# epidata_call %>%
18-
# fetch_debug(format_type = "csv") %>%
19-
# readr::write_rds(testthat::test_path("data/test-csv.rds"))
20-
mockery::stub(fetch_csv, "httr::content", readRDS(testthat::test_path("data/test-csv.rds")))
2110

22-
# This test compares the output of a tibble using fetch_tbl and fetch_csv.
23-
#
24-
# 1) fetch_tbl calls fetch_classic, which requests the default (classic
25-
# format) from the API, uses jsonlite::fromJSON to convert the underlying data
26-
# to a data.frame, and finally applies parse_data_frame is used to do the data
27-
# type coersion specified by the epidata_call metadata.
28-
# 2) fetch_csv requests the csv format from the API, then uses readr::read_csv
29-
# to get a data.frame, and has its own methods to enforce data types.
30-
tbl_out <- epidata_call %>% fetch_tbl()
31-
csv_out <- epidata_call %>% fetch_csv()
32-
expect_identical(tbl_out, csv_out)
11+
local_mocked_bindings(
12+
request_impl = function(...) NULL,
13+
.package = "epidatr"
14+
)
15+
local_mocked_bindings(
16+
# RDS file generated with
17+
# epidata_call %>%
18+
# fetch_debug(format_type = "classic") %>%
19+
# readr::write_rds(testthat::test_path("data/test-classic.rds"))
20+
content = function(...) readRDS(testthat::test_path("data/test-classic.rds")),
21+
.package = "httr"
22+
)
3323

34-
# # This test compares fetch_tbl with the output of fetch, which should be identical.
24+
tbl_out <- epidata_call %>% fetch_tbl()
3525
out <- epidata_call %>% fetch()
3626
expect_identical(out, tbl_out)
3727
})
@@ -45,14 +35,25 @@ test_that("fetch_tbl warns on non-success", {
4535
time_values = epirange("2020-06-01", "2020-08-01"),
4636
geo_values = "ca,fl"
4737
)
38+
39+
local_mocked_bindings(
40+
request_impl = function(...) NULL,
41+
.package = "epidatr"
42+
)
43+
local_mocked_bindings(
44+
content = function(...) NULL,
45+
.package = "httr"
46+
)
4847
artificial_warning <- "* This is a warning with a leading asterisk and {braces} to make sure we don't have bulleting/glue bugs."
49-
debug_response_content_triplet <-
50-
# see generation code above
51-
readRDS(testthat::test_path("data/test-classic.rds")) %>%
48+
debug_triplet <- readRDS(testthat::test_path("data/test-classic.rds")) %>%
5249
jsonlite::fromJSON() %>%
53-
`[[<-`("message", "* This is a warning with a leading asterisk and {braces} to make sure we don't have bulleting/glue bugs.")
54-
mockery::stub(fetch_classic, "jsonlite::fromJSON", debug_response_content_triplet)
55-
mockery::stub(fetch_tbl, "fetch_classic", fetch_classic)
50+
`[[<-`("message", artificial_warning)
51+
local_mocked_bindings(
52+
# see generation code above
53+
fromJSON = function(...) debug_triplet,
54+
.package = "jsonlite"
55+
)
56+
5657
expect_warning(epidata_call %>% fetch_tbl(),
5758
regexp = paste0("epidata warning: ", artificial_warning),
5859
fixed = TRUE

0 commit comments

Comments
 (0)