Skip to content

Commit 9282f34

Browse files
authored
Merge pull request #118 from dsweber2/extendingTests
Extending tests and CI update to check the test level for any pull request
2 parents bf98ce6 + 403f1a0 commit 9282f34

16 files changed

+183
-25
lines changed

.github/workflows/ci.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
name: ci
22

3-
on: [push]
3+
on:
4+
workflow_dispatch: #get a button to trigger it by hand
5+
push:
46

57
jobs:
68
build:

.github/workflows/test-coverage.yml

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2+
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3+
on:
4+
workflow_dispatch: #get a button to trigger it by hand
5+
push:
6+
branches: [main, dev]
7+
pull_request:
8+
9+
name: test-coverage
10+
11+
jobs:
12+
test-coverage:
13+
runs-on: ubuntu-latest
14+
env:
15+
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
16+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
17+
18+
steps:
19+
- uses: actions/checkout@v3
20+
21+
- uses: r-lib/actions/setup-r@v2
22+
with:
23+
use-public-rspm: true
24+
25+
- uses: r-lib/actions/setup-r-dependencies@v2
26+
with:
27+
extra-packages: any::covr
28+
needs: coverage
29+
30+
- name: Test coverage
31+
run: |
32+
covr::codecov(
33+
quiet = FALSE,
34+
clean = FALSE,
35+
install_path = file.path(Sys.getenv("RUNNER_TEMP"), "package")
36+
)
37+
shell: Rscript {0}
38+
39+
- name: Show testthat output
40+
if: always()
41+
run: |
42+
## --------------------------------------------------------------------
43+
find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true
44+
shell: bash
45+
46+
- name: Upload test results
47+
if: failure()
48+
uses: actions/upload-artifact@v3
49+
with:
50+
name: coverage-test-failures
51+
path: ${{ runner.temp }}/package
52+
53+
- name: Upload coverage reports to Codecov
54+
uses: codecov/codecov-action@v3

R/covidcast.R

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ print.covidcast_data_signal <- function(signal, ...) {
3939

4040
parse_source <- function(source, base_url) {
4141
class(source) <- c("covidcast_data_source", class(source))
42-
signals <- do.call(c, lapply(source$signals, parse_signal, base_url = base_url))
42+
signals <- do.call(c, unname(lapply(source$signals, parse_signal, base_url = base_url)))
4343
class(signals) <- c("covidcast_data_signal_list", class(signals))
4444
source$signals <- signals
4545
r <- list()
@@ -113,7 +113,7 @@ covidcast_epidata <- function(base_url = global_base_url) {
113113
if (response$status_code != 200) {
114114
# 500, 429, 401 are possible
115115
msg <- "fetch data from API"
116-
if (httr::http_type(response) == "text/html") {
116+
if (httr::http_type(response) == "text/html" & length(response$content) > 0) {
117117
# grab the error information out of the returned HTML document
118118
msg <- paste(msg, ":", xml2::xml_text(xml2::xml_find_all(
119119
xml2::read_html(content(response, "text")),

R/model.R

-20
Original file line numberDiff line numberDiff line change
@@ -150,26 +150,6 @@ parse_api_week <- function(value) {
150150
MMWRweek::MMWRweek2Date(years, weeks)
151151
}
152152

153-
fields_to_predicate <- function(fields = NULL) {
154-
if (is.null(fields)) {
155-
return(function(x) {
156-
TRUE
157-
})
158-
}
159-
to_include <- c()
160-
to_exclude <- c()
161-
for (f in fields) {
162-
if (substr(f, 1, 2) == "-") {
163-
to_exclude <- c(to_exclude, substr(f, 2, length(f)))
164-
} else {
165-
to_include <- c(to_include, f)
166-
}
167-
}
168-
function(x) {
169-
!(x %in% to_exclude) && (length(to_include) == 0 || x %in% to_include)
170-
}
171-
}
172-
173153
#' @importFrom checkmate test_character test_class test_date test_integerish test_list
174154
parse_timeset_input <- function(value) {
175155
if (is.null(value)) {

README.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# delphi Epidata R client
22

33
[![License: MIT][mit-image]][mit-url] [![Github Actions][github-actions-image]][github-actions-url]
4+
[![codecov](https://codecov.io/gh/dsweber2/epidatr/branch/dev/graph/badge.svg?token=jVHL9eHZNZ)](https://codecov.io/gh/dsweber2/epidatr)
45

56
## Documentation
67

@@ -19,13 +20,17 @@ functions have been replaced by the `fetch()` function, which almost always
1920
returns a tibble, except when used with a limited number of older endpoints
2021
(such as `delphi()` and `meta()`), where it will output a nested list structure.
2122
If you encounter an error like
23+
2224
```{r}
2325
Error in fetch_tbl(.) : could not find function "fetch_tbl"
2426
```
25-
please update to use `fetch()` instead. If instead you encounter
27+
28+
please update to use `fetch()` instead. If instead you encounter
29+
2630
```{r}
2731
Error in fetch(.) : could not find function "fetch"
2832
```
33+
2934
please update to the newest `epidatr`.
3035

3136
Note (2022-08-02): the package that this installs is being renamed from
@@ -54,6 +59,7 @@ a separate key that needs to be passed as an argument.
5459
## Development Environment
5560

5661
Relevant R commands
62+
5763
```r
5864
install.packages(c('devtools', 'pkgdown', 'styler', 'lintr')) # install dev dependencies
5965
devtools::install_deps(dependencies = TRUE) # install package dependencies
424 Bytes
Binary file not shown.

tests/testthat/data/http401.rds

4.36 KB
Binary file not shown.
14.1 KB
Binary file not shown.
2.56 KB
Binary file not shown.

tests/testthat/data/test-http401.rds

4.36 KB
Binary file not shown.

tests/testthat/data/test-http500.rds

4.7 KB
Binary file not shown.
5.24 KB
Binary file not shown.

tests/testthat/test-covidcast.R

+29
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,32 @@ test_that("covidcast", {
55
covidcast("fb-survey", "smoothed_cli", "nation", "day", "us", epirange(20210405, 20210410))
66
)
77
})
8+
9+
# quite minimal, could probably use some checks that the fields are as desired
10+
test_that("dataframe converters", {
11+
res <- covidcast_epidata()$sources %>% as.data.frame()
12+
expect_identical(class(res), "data.frame")
13+
res <- covidcast_epidata()$signals %>% as.data.frame()
14+
expect_identical(class(res), "data.frame")
15+
})
16+
17+
test_that("http errors", {
18+
# generated with
19+
# response <- httr::RETRY("GET",
20+
# url = "https://httpbin.org/status/400",
21+
# query = list(),
22+
# terminate_on = c(400, 401, 403, 405, 414, 500),
23+
# http_headers,
24+
# httr::authenticate("epidata", get_auth_key())
25+
# ) %>% readr::write_rds(testthat::test_path("data/test-do_request-httpbin.rds"))
26+
local_mocked_bindings(
27+
do_request = function(...) readRDS(testthat::test_path("data/test-do_request-httpbin.rds"))
28+
)
29+
expect_error(covidcast_epidata(), class = "http_400")
30+
})
31+
32+
33+
test_that("name completion", {
34+
all_names <- names(covidcast_epidata()$signals)
35+
expect_identical(all_names, all_names)
36+
})

tests/testthat/test-epidatacall.R

+57-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
test_that("request_impl http errors", {
2+
# should give a 401 error
3+
epidata_call <- pvt_cdc(auth = "ImALittleTeapot", epiweeks = epirange(202003, 202304), locations = "ma")
4+
local_mocked_bindings(
5+
# generated via
6+
# url <- full_url(epidata_call)
7+
# params <- request_arguments(epidata_call, "csv", NULL)
8+
# result <- do_request(url, params) %>% readr::write_rds(testthat::test_path("data/test-http401.rds"))
9+
do_request = function(...) readRDS(testthat::test_path("data/test-http401.rds")),
10+
)
11+
expect_error(response <- epidata_call %>% request_impl("csv"), class = "http_401")
12+
13+
# should give a 500 error (the afhsb endpoint is removed)
14+
15+
# generated via
16+
# epidata_call <- pvt_afhsb(auth = Sys.getenv("SECRET_API_AUTH_AFHSB"), locations = "mn", epiweeks = epirange(202002, 202110), flu_types = "flu1")
17+
# url <- full_url(epidata_call)
18+
# params <- request_arguments(epidata_call, "csv", NULL)
19+
# response <- do_request(url, params) %>% readr::write_rds(testthat::test_path("data/test-http500.rds"))
20+
local_mocked_bindings(
21+
do_request = function(...) readRDS(testthat::test_path("data/test-http500.rds"))
22+
)
23+
expect_error(response <- epidata_call %>% request_impl("csv"), class = "http_500")
24+
})
25+
126
test_that("fetch and fetch_tbl", {
227
epidata_call <- covidcast(
328
data_source = "jhu-csse",
@@ -7,7 +32,6 @@ test_that("fetch and fetch_tbl", {
732
time_values = epirange("2020-06-01", "2020-08-01"),
833
geo_values = "ca,fl"
934
)
10-
1135
local_mocked_bindings(
1236
request_impl = function(...) NULL,
1337
.package = "epidatr"
@@ -24,6 +48,18 @@ test_that("fetch and fetch_tbl", {
2448
tbl_out <- epidata_call %>% fetch_tbl()
2549
out <- epidata_call %>% fetch()
2650
expect_identical(out, tbl_out)
51+
52+
local_mocked_bindings(
53+
# RDS file generated with
54+
# epidata_call %>%
55+
# fetch_debug(format_type = "classic", fields = c("time_value", "value")) %>%
56+
# readr::write_rds(testthat::test_path("data/test-narrower-fields.rds"))
57+
content = function(...) readRDS(testthat::test_path("data/test-narrower-fields.rds")),
58+
.package = "httr"
59+
)
60+
# testing that the fields fill as expected
61+
res <- epidata_call %>% fetch(fields = c("time_value", "value"))
62+
expect_equal(res, tbl_out[c("time_value", "value")])
2763
})
2864

2965
test_that("fetch_tbl warns on non-success", {
@@ -61,3 +97,23 @@ test_that("fetch_tbl warns on non-success", {
6197
# fixed = TRUE
6298
# )
6399
})
100+
101+
test_that("classic only fetch", {
102+
# delphi is an example endpoint that only suports the classic call
103+
epidata_call <- delphi(system = "ec", epiweek = 201501)
104+
local_mocked_bindings(
105+
# generated using
106+
# epidata_call %>%
107+
# fetch_debug(format_type = "classic") %>%
108+
# readr::write_rds(testthat::test_path("data/test-classic-only.rds"))
109+
content = function(...) readRDS(testthat::test_path("data/test-classic-only.rds")),
110+
.package = "httr"
111+
)
112+
# make sure that fetch actually uses the classic method on endpoints that only support the classic
113+
fetch_out <- epidata_call %>% fetch()
114+
fetch_classic_out <- epidata_call %>% fetch_classic()
115+
expect_identical(fetch_out, fetch_classic_out)
116+
117+
# making sure that fetch_tbl and throws the expected error on classic only
118+
expect_error(epidata_call %>% fetch_tbl(), class = "only_supports_classic_format")
119+
})

tests/testthat/test-model.R

+27
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,30 @@ test_that("`parse_timeset_input` on valid inputs", {
4646
# NULL: allow this as a missing argument marker
4747
expect_identical(parse_timeset_input(NULL), NULL)
4848
})
49+
50+
test_that("null parsing", {
51+
# parse_data_frame (df[[info$name]] = NULL)-> parse_value
52+
epidata_call <- flusurv(locations = "ca", epiweeks = 202001)
53+
# mocked data generated with
54+
# epidata_call %>%
55+
# fetch_classic() %>%
56+
# readr::write_rds(testthat::test_path("data/flusurv-epiweeks.rds"))
57+
mock_df <- as.data.frame(readr::read_rds(testthat::test_path("data/flusurv-epiweeks.rds")))
58+
metadata <- epidata_call$meta
59+
mock_df[[metadata[[1]]$name]][1] <- list(NULL)
60+
mock_df[[metadata[[2]]$name]] <- c(TRUE)
61+
epidata_call$meta[[2]]$type <- "bool"
62+
res <- parse_data_frame(epidata_call, mock_df) %>% as_tibble()
63+
# expect_null(res[["release_date"]]) # this is actually a list
64+
expect_true(res$location)
65+
66+
# if the call has no metadata, return the whole frame as is
67+
epidata_call$meta <- NULL
68+
expect_identical(parse_data_frame(epidata_call, mock_df), mock_df)
69+
})
70+
71+
test_that("parse invalid time", {
72+
vale <- list(3)
73+
vale$class <- "my nonexistant class"
74+
expect_error(parse_timeset_input(vale))
75+
})

tests/testthat/test-request.R

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
test_that("requesting works", {
2+
res <- do_request("https://httpbin.org/status/414", list())
3+
expect_equal(res$status_code, 414)
4+
})

0 commit comments

Comments
 (0)