From b8c9d2cef024f5333199781062a4f1261fc4fc15 Mon Sep 17 00:00:00 2001 From: rafapereirabr Date: Sun, 1 Nov 2026 15:46:13 -0300 Subject: [PATCH] Name every argument in the overnight-times code Adds a CLAUDE.md rule that R function calls never use positional arguments, and applies it to the code and tests this branch added: every call names its arguments (values passed through ... stay unnamed), long calls are split one argument per line, and long test_that() headers use desc = and code = on their own lines. The string_to_seconds() mock in test-get_trip_duration.R now uses the real argument name. set_min_speed() docs are rewrapped. Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 5 + R/build_graph.R | 2 +- R/filter_by_time_of_day.R | 2 +- R/fix_gtfs.R | 2 +- R/fix_overnight_times.R | 206 ++++--- R/get_dwell_time.R | 2 +- R/get_route_frequency.R | 6 +- R/get_stop_frequency.R | 8 +- R/get_summary.R | 2 +- R/get_trip_duration.R | 2 +- R/get_trip_length.R | 2 +- R/get_trip_segment_duration.R | 2 +- R/get_trip_speed.R | 2 +- R/interpolate_stop_times.R | 2 +- R/set_dwell_time.R | 2 +- R/set_max_speed.R | 2 +- R/set_min_speed.R | 6 +- R/set_route_frequency.R | 2 +- R/set_trip_speed.R | 2 +- man/set_min_speed.Rd | 6 +- tests/testthat/setup-overnight_feed.R | 2 +- tests/testthat/test-build_graph.R | 30 +- tests/testthat/test-filter_by_time_of_day.R | 42 +- tests/testthat/test-fix_gtfs.R | 23 +- tests/testthat/test-fix_overnight_times.R | 556 +++++++++++------- tests/testthat/test-get_dwell_time.R | 83 +-- tests/testthat/test-get_route_frequency.R | 81 +-- tests/testthat/test-get_stop_frequency.R | 71 ++- tests/testthat/test-get_trip_duration.R | 97 +-- tests/testthat/test-get_trip_length.R | 59 +- .../testthat/test-get_trip_segment_duration.R | 65 +- tests/testthat/test-get_trip_speed.R | 24 +- tests/testthat/test-interpolate_stop_times.R | 36 +- tests/testthat/test-set_dwell_time.R | 107 ++-- tests/testthat/test-set_max_speed.R | 57 +- tests/testthat/test-set_min_dwell_time.R | 23 +- tests/testthat/test-set_route_frequency.R | 52 +- tests/testthat/test-set_trip_speed.R | 69 ++- 38 files changed, 1027 insertions(+), 715 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index db311d71..90ac5a16 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,6 +26,11 @@ License MIT. Docs: . `MEMORY.md`. - **Code style.** Always use the convention `package::function()`. Exceptions are functions from ggplot2 and special data.table operators such as `:=`. +- **Explicit argument names.** Never use positional arguments. Every + function call in R names its arguments explicitly, e.g. + `get_trip_length(gtfs = gtfs, trip_id = ids, unit = "km")`, never + `get_trip_length(gtfs, ids, unit = "km")`. (Values passed through `...`, + as in `c()` or `paste0()`, have no argument name to give.) Conventions are in [`.claude/rules/r-package-conventions.md`](.claude/rules/r-package-conventions.md); gates are in [`.claude/rules/quality-gates.md`](.claude/rules/quality-gates.md). diff --git a/R/build_graph.R b/R/build_graph.R index a7c5e1d3..620fc975 100644 --- a/R/build_graph.R +++ b/R/build_graph.R @@ -232,7 +232,7 @@ build_graph <- function(gtfs, # 'frequencies' come from its start and end times, which are fixed too # (fields of the wrong class are reported later, when they are used) - gtfs <- fix_overnight_in_call(gtfs, frequencies = TRUE) + gtfs <- fix_overnight_in_call(gtfs = gtfs, frequencies = TRUE) network <- build_service_network( gtfs, diff --git a/R/filter_by_time_of_day.R b/R/filter_by_time_of_day.R index 69ecc8a6..ac746b3c 100644 --- a/R/filter_by_time_of_day.R +++ b/R/filter_by_time_of_day.R @@ -142,7 +142,7 @@ filter_by_time_of_day <- function(gtfs, # they are compared with the time of day as they should be. the returned # feed keeps them fixed - gtfs <- fix_overnight_in_call(gtfs, frequencies = TRUE) + gtfs <- fix_overnight_in_call(gtfs = gtfs, frequencies = TRUE) # if the gtfs contains a frequencies table, it's important to keep the # stop_times of the trips listed in there intact. diff --git a/R/fix_gtfs.R b/R/fix_gtfs.R index 655375ed..308e4c41 100644 --- a/R/fix_gtfs.R +++ b/R/fix_gtfs.R @@ -155,7 +155,7 @@ fix_gtfs <- function( # fix times after midnight before the steps that use the times, which skip # the spans that go back - gtfs_fixed <- fix_overnight_times(gtfs_fixed) + gtfs_fixed <- fix_overnight_times(gtfs = gtfs_fixed) # cap max speed. this is done before interpolating, so the interpolated # times follow the capped times diff --git a/R/fix_overnight_times.R b/R/fix_overnight_times.R index 0b842d7a..a4678c0b 100644 --- a/R/fix_overnight_times.R +++ b/R/fix_overnight_times.R @@ -75,28 +75,28 @@ #' #' @export fix_overnight_times <- function(gtfs) { - gtfs <- assert_and_assign_gtfs_object(gtfs) + gtfs <- assert_and_assign_gtfs_object(gtfs = gtfs) gtfsio::assert_field_class( - gtfs, - "stop_times", - c("trip_id", "stop_sequence", "arrival_time", "departure_time"), - c("character", "integer", "character", "character") + x = gtfs, + file = "stop_times", + fields = c("trip_id", "stop_sequence", "arrival_time", "departure_time"), + classes = c("character", "integer", "character", "character") ) - if (gtfsio::check_file_exists(gtfs, "frequencies")) { + if (gtfsio::check_file_exists(x = gtfs, files = "frequencies")) { gtfsio::assert_field_class( - gtfs, - "frequencies", - c("start_time", "end_time"), - c("character", "character") + x = gtfs, + file = "frequencies", + fields = c("start_time", "end_time"), + classes = c("character", "character") ) } - gtfs <- fix_overnight_stop_times(gtfs) - gtfs <- fix_overnight_frequencies(gtfs) + gtfs <- fix_overnight_stop_times(gtfs = gtfs) + gtfs <- fix_overnight_frequencies(gtfs = gtfs) - return(gtfs) + return(value = gtfs) } @@ -135,8 +135,10 @@ fix_overnight_stop_times <- function( # rows with a missing trip_id or stop_sequence can't be placed in a trip, # so they are left alone - is_candidate <- !is.na(stop_times$trip_id) & !is.na(stop_times$stop_sequence) - if (!is.null(trip_id)) { + has_trip <- !is.na(x = stop_times$trip_id) + has_sequence <- !is.na(x = stop_times$stop_sequence) + is_candidate <- has_trip & has_sequence + if (!is.null(x = trip_id)) { is_candidate <- is_candidate & stop_times$trip_id %chin% trip_id } @@ -145,9 +147,12 @@ fix_overnight_stop_times <- function( # the radix sort of order() fails on ids in a native encoding with # non-ASCII characters (e.g. on Windows) - rows <- which(is_candidate) + rows <- which(x = is_candidate) candidate_trips <- stop_times$trip_id[rows] - trip_number <- data.table::chmatch(candidate_trips, unique(candidate_trips)) + trip_number <- data.table::chmatch( + x = candidate_trips, + table = unique(x = candidate_trips) + ) ord <- order(trip_number, stop_times$stop_sequence[rows], method = "radix") rows <- rows[ord] trip_number <- trip_number[ord] @@ -162,40 +167,45 @@ fix_overnight_stop_times <- function( rows_secs <- function(time_col) { secs_col <- paste0(time_col, "_secs") - if (secs_col %chin% names(stop_times)) { - return(stop_times[[secs_col]][rows]) + if (secs_col %chin% names(x = stop_times)) { + return(value = stop_times[[secs_col]][rows]) } - return(string_to_seconds(stop_times[[time_col]][rows])) + return(value = string_to_seconds(string = stop_times[[time_col]][rows])) } - n_rows <- length(rows) + n_rows <- length(x = rows) secs <- withCallingHandlers( - as.numeric(rbind(rows_secs("arrival_time"), rows_secs("departure_time"))), + expr = as.numeric( + x = rbind( + rows_secs(time_col = "arrival_time"), + rows_secs(time_col = "departure_time") + ) + ), gtfstools_malformed_time = function(cnd) { - if (!warn) invokeRestart("muffleWarning") + if (!warn) invokeRestart(r = "muffleWarning") } ) - row <- rep(rows, each = 2L) - is_arrival <- rep(c(TRUE, FALSE), times = n_rows) + row <- rep(x = rows, each = 2L) + is_arrival <- rep(x = c(TRUE, FALSE), times = n_rows) # trips are told apart by the numbers they were sorted by, which is cheaper # than comparing their ids on the interleaved times - trip_run <- rep(trip_number, each = 2L) + trip_run <- rep(x = trip_number, each = 2L) - is_known <- !is.na(secs) + is_known <- !is.na(x = secs) secs <- secs[is_known] row <- row[is_known] is_arrival <- is_arrival[is_known] trip_run <- trip_run[is_known] - n <- length(secs) + n <- length(x = secs) if (n == 0) { - return(if (detect_only) FALSE else gtfs) + return(value = if (detect_only) FALSE else gtfs) } is_first <- c(TRUE, trip_run[-1L] != trip_run[-n]) - trip_idx <- cumsum(is_first) + trip_idx <- cumsum(x = is_first) # a step back of more than 12 hours between consecutive times of a trip # crosses midnight, so the times after it are one day later than written. @@ -203,9 +213,9 @@ fix_overnight_stop_times <- function( # that mix "24:xx" and "00:xx" times are fixed too. round() rounds a step of # exactly 12 hours to 0 - step <- c(0, diff(secs)) + step <- c(0, diff(x = secs)) step[is_first] <- 0 - days <- cumsum(-round(step / 86400)) + days <- cumsum(x = -round(x = step / 86400)) # the days are counted from the start of each trip, and kept from going # below 0 by subtracting their running minimum within the trip, so times are @@ -214,19 +224,19 @@ fix_overnight_stop_times <- function( # previous ones, so a single cummin() restarts at the start of each trip days <- days - days[is_first][trip_idx] - trip_shift <- trip_idx * (2 * max(abs(days)) + 1) - days <- days - (cummin(days - trip_shift) + trip_shift) + trip_shift <- trip_idx * (2 * max(abs(x = days)) + 1) + days <- days - (cummin(x = days - trip_shift) + trip_shift) fixed <- secs + days * 86400 # steps that still go back are left as they are, with a warning - is_backwards <- !is_first & c(0, diff(fixed)) < 0 + is_backwards <- !is_first & c(0, diff(x = fixed)) < 0 if (warn && any(is_backwards)) { - backwards_trips <- unique(stop_times$trip_id[row[is_backwards]]) - abbreviated <- abbreviate_ids(backwards_trips) + backwards_trips <- unique(x = stop_times$trip_id[row[is_backwards]]) + abbreviated <- abbreviate_ids(ids = backwards_trips) cli::cli_warn( - c( + message = c( paste0( "{length(backwards_trips)} trip{?s} {?has/have} times earlier ", "than the previous time of the trip, which {?was/were} not fixed: ", @@ -243,10 +253,10 @@ fix_overnight_stop_times <- function( is_changed <- days > 0 if (detect_only) { - return(any(is_changed)) + return(value = any(is_changed)) } if (!any(is_changed)) { - return(gtfs) + return(value = gtfs) } # seconds_to_string() can't write times later than 9999:59:59 @@ -254,10 +264,10 @@ fix_overnight_stop_times <- function( is_invalid <- is_changed & fixed > max_time_secs if (any(is_invalid)) { - invalid_trips <- unique(stop_times$trip_id[row[is_invalid]]) - abbreviated <- abbreviate_ids(invalid_trips) + invalid_trips <- unique(x = stop_times$trip_id[row[is_invalid]]) + abbreviated <- abbreviate_ids(ids = invalid_trips) cli::cli_abort( - paste0( + message = paste0( "Fixing the times after midnight results in times later than ", "{.val 9999:59:59} in the following ", "{cli::qty(length(invalid_trips))}trip{?s}: ", @@ -268,35 +278,35 @@ fix_overnight_stop_times <- function( } if (!by_reference) { - stop_times <- data.table::copy(stop_times) + stop_times <- data.table::copy(x = stop_times) } is_arr_changed <- is_changed & is_arrival data.table::set( - stop_times, + x = stop_times, i = row[is_arr_changed], j = "arrival_time", - value = seconds_to_string(as.integer(fixed[is_arr_changed])) + value = seconds_to_string(seconds = as.integer(x = fixed[is_arr_changed])) ) is_dep_changed <- is_changed & !is_arrival data.table::set( - stop_times, + x = stop_times, i = row[is_dep_changed], j = "departure_time", - value = seconds_to_string(as.integer(fixed[is_dep_changed])) + value = seconds_to_string(seconds = as.integer(x = fixed[is_dep_changed])) ) # refresh pre-existing *_secs columns, which other functions use as-is refresh_secs_columns( - stop_times, - c("arrival_time", "departure_time"), - unique(row[is_changed]) + dt = stop_times, + time_cols = c("arrival_time", "departure_time"), + rows = unique(x = row[is_changed]) ) gtfs$stop_times <- stop_times - return(gtfs) + return(value = gtfs) } @@ -310,24 +320,24 @@ fix_overnight_stop_times <- function( #' @keywords internal fix_overnight_frequencies <- function(gtfs) { frequencies <- gtfs$frequencies - if (is.null(frequencies)) { - return(gtfs) + if (is.null(x = frequencies)) { + return(value = gtfs) } - start <- time_secs(frequencies, "start_time") - end <- time_secs(frequencies, "end_time") - wrapped <- which(end < start) + start <- time_secs(dt = frequencies, time_col = "start_time") + end <- time_secs(dt = frequencies, time_col = "end_time") + wrapped <- which(x = end < start) - if (length(wrapped) == 0) { - return(gtfs) + if (length(x = wrapped) == 0) { + return(value = gtfs) } fixed <- end[wrapped] + - 86400 * (floor((start[wrapped] - end[wrapped]) / 86400) + 1) + 86400 * (floor(x = (start[wrapped] - end[wrapped]) / 86400) + 1) if (any(fixed > max_time_secs)) { cli::cli_abort( - paste0( + message = paste0( "Fixing the times after midnight results in times later than ", "{.val 9999:59:59} in {.field frequencies}." ), @@ -335,17 +345,17 @@ fix_overnight_frequencies <- function(gtfs) { ) } - frequencies <- data.table::copy(frequencies) + frequencies <- data.table::copy(x = frequencies) data.table::set( - frequencies, + x = frequencies, i = wrapped, j = "end_time", - value = seconds_to_string(as.integer(fixed)) + value = seconds_to_string(seconds = as.integer(x = fixed)) ) - refresh_secs_columns(frequencies, "end_time", wrapped) + refresh_secs_columns(dt = frequencies, time_cols = "end_time", rows = wrapped) gtfs$frequencies <- frequencies - return(gtfs) + return(value = gtfs) } @@ -367,39 +377,41 @@ fix_overnight_frequencies <- function(gtfs) { #' @keywords internal has_overnight_trips <- function(gtfs) { is_stop_times_valid <- gtfsio::check_field_class( - gtfs, - "stop_times", - c("trip_id", "stop_sequence", "arrival_time", "departure_time"), - c("character", "integer", "character", "character") + x = gtfs, + file = "stop_times", + fields = c("trip_id", "stop_sequence", "arrival_time", "departure_time"), + classes = c("character", "integer", "character", "character") ) # the check is silent: malformed times are reported by the functions that # use the times - if (isTRUE(is_stop_times_valid)) { + if (isTRUE(x = is_stop_times_valid)) { has_wrapped_times <- fix_overnight_stop_times( - gtfs, + gtfs = gtfs, warn = FALSE, detect_only = TRUE ) - if (has_wrapped_times) return(TRUE) + if (has_wrapped_times) return(value = TRUE) } is_frequencies_valid <- gtfsio::check_field_class( - gtfs, - "frequencies", - c("start_time", "end_time"), - c("character", "character") + x = gtfs, + file = "frequencies", + fields = c("start_time", "end_time"), + classes = c("character", "character") ) - if (isTRUE(is_frequencies_valid)) { + if (isTRUE(x = is_frequencies_valid)) { is_wrapped <- withCallingHandlers( - time_secs(gtfs$frequencies, "end_time") < - time_secs(gtfs$frequencies, "start_time"), - gtfstools_malformed_time = function(cnd) invokeRestart("muffleWarning") + expr = time_secs(dt = gtfs$frequencies, time_col = "end_time") < + time_secs(dt = gtfs$frequencies, time_col = "start_time"), + gtfstools_malformed_time = function(cnd) { + invokeRestart(r = "muffleWarning") + } ) - return(any(is_wrapped, na.rm = TRUE)) + return(value = any(is_wrapped, na.rm = TRUE)) } - return(FALSE) + return(value = FALSE) } @@ -430,15 +442,15 @@ fix_overnight_in_call <- function( # own assertions report them is_stop_times_valid <- gtfsio::check_field_class( - gtfs, - "stop_times", - c("trip_id", "stop_sequence", "arrival_time", "departure_time"), - c("character", "integer", "character", "character") + x = gtfs, + file = "stop_times", + fields = c("trip_id", "stop_sequence", "arrival_time", "departure_time"), + classes = c("character", "integer", "character", "character") ) - if (isTRUE(is_stop_times_valid)) { + if (isTRUE(x = is_stop_times_valid)) { gtfs <- fix_overnight_stop_times( - gtfs, - trip_id, + gtfs = gtfs, + trip_id = trip_id, warn = FALSE, by_reference = by_reference ) @@ -446,15 +458,15 @@ fix_overnight_in_call <- function( if (frequencies) { is_frequencies_valid <- gtfsio::check_field_class( - gtfs, - "frequencies", - c("start_time", "end_time"), - c("character", "character") + x = gtfs, + file = "frequencies", + fields = c("start_time", "end_time"), + classes = c("character", "character") ) - if (isTRUE(is_frequencies_valid)) { - gtfs <- fix_overnight_frequencies(gtfs) + if (isTRUE(x = is_frequencies_valid)) { + gtfs <- fix_overnight_frequencies(gtfs = gtfs) } } - return(gtfs) + return(value = gtfs) } diff --git a/R/get_dwell_time.R b/R/get_dwell_time.R index eaee0972..74f0728f 100644 --- a/R/get_dwell_time.R +++ b/R/get_dwell_time.R @@ -108,7 +108,7 @@ get_dwell_time <- function(gtfs, # times after midnight written as early morning times are fixed first, so # they don't go back - gtfs <- fix_overnight_in_call(gtfs, trip_id) + gtfs <- fix_overnight_in_call(gtfs = gtfs, trip_id = trip_id) rows <- select_dwell_time_calls(gtfs$stop_times, trip_id, stop_id) diff --git a/R/get_route_frequency.R b/R/get_route_frequency.R index 7ddd6a94..54d6e8a8 100644 --- a/R/get_route_frequency.R +++ b/R/get_route_frequency.R @@ -164,7 +164,11 @@ get_trip_departures <- function(gtfs, trip_id) { # times after midnight written as early morning times are fixed first, so # each trip departs at its real time. only the relevant trips are fixed - gtfs <- fix_overnight_in_call(gtfs, relevant_trips, frequencies = TRUE) + gtfs <- fix_overnight_in_call( + gtfs = gtfs, + trip_id = relevant_trips, + frequencies = TRUE + ) # the departures of trips listed in 'frequencies' come from the # 'frequencies' table, while their 'stop_times' entries are just templates diff --git a/R/get_stop_frequency.R b/R/get_stop_frequency.R index f3c3af9e..55ab87af 100644 --- a/R/get_stop_frequency.R +++ b/R/get_stop_frequency.R @@ -160,9 +160,13 @@ get_stop_frequency <- function(gtfs, # the departures are compared with the time of day as they should be. only # the relevant trips are fixed - gtfs <- fix_overnight_in_call(gtfs, relevant_trips, frequencies = TRUE) + gtfs <- fix_overnight_in_call( + gtfs = gtfs, + trip_id = relevant_trips, + frequencies = TRUE + ) - if (is.null(relevant_trips)) { + if (is.null(x = relevant_trips)) { stop_times <- gtfs$stop_times[ , .( diff --git a/R/get_summary.R b/R/get_summary.R index dc31e543..b3ce2e3c 100644 --- a/R/get_summary.R +++ b/R/get_summary.R @@ -314,7 +314,7 @@ get_summary <- function( # times after midnight written as early morning times are fixed once, here, # so the functions used below find them already fixed - gtfs <- fix_overnight_in_call(gtfs, frequencies = TRUE) + gtfs <- fix_overnight_in_call(gtfs = gtfs, frequencies = TRUE) feed <- gtfs if (!is.null(agency_id)) { diff --git a/R/get_trip_duration.R b/R/get_trip_duration.R index 53257fbd..618cdc4b 100644 --- a/R/get_trip_duration.R +++ b/R/get_trip_duration.R @@ -93,7 +93,7 @@ get_trip_duration <- function(gtfs, # they don't go back. without an integer stop_sequence the times can't be # ordered, so they are used as written - gtfs <- fix_overnight_in_call(gtfs, trip_id) + gtfs <- fix_overnight_in_call(gtfs = gtfs, trip_id = trip_id) # select trip_ids to get duration of and raise warning if a given trip_id # doesn't exist in 'stop_times' diff --git a/R/get_trip_length.R b/R/get_trip_length.R index 3f3ccac2..956ad3b8 100644 --- a/R/get_trip_length.R +++ b/R/get_trip_length.R @@ -169,7 +169,7 @@ get_trip_length <- function(gtfs, # changed by the fix, so by = "trip" doesn't need it if (is_windowed && by == "segment") { - gtfs <- fix_overnight_in_call(gtfs, trip_id) + gtfs <- fix_overnight_in_call(gtfs = gtfs, trip_id = trip_id) } if (is_windowed) { diff --git a/R/get_trip_segment_duration.R b/R/get_trip_segment_duration.R index 1d412450..d4108aa6 100644 --- a/R/get_trip_segment_duration.R +++ b/R/get_trip_segment_duration.R @@ -106,7 +106,7 @@ get_trip_segment_duration <- function(gtfs, # times after midnight written as early morning times are fixed first, so # they don't go back - gtfs <- fix_overnight_in_call(gtfs, trip_id) + gtfs <- fix_overnight_in_call(gtfs = gtfs, trip_id = trip_id) # select the trips to get the segments' durations of and raise a warning if # a given trip_id doesn't exist in 'stop_times' diff --git a/R/get_trip_speed.R b/R/get_trip_speed.R index b43fcb62..ccd78135 100644 --- a/R/get_trip_speed.R +++ b/R/get_trip_speed.R @@ -148,7 +148,7 @@ get_trip_speed <- function( # again. without an integer stop_sequence the times can't be ordered, so # they are used as written - gtfs <- fix_overnight_in_call(gtfs, trip_id) + gtfs <- fix_overnight_in_call(gtfs = gtfs, trip_id = trip_id) # get_trip_length() keeps only the trips or segments within the time of # day, so the durations joined to them below are filtered too diff --git a/R/interpolate_stop_times.R b/R/interpolate_stop_times.R index fbd5101f..74061e08 100644 --- a/R/interpolate_stop_times.R +++ b/R/interpolate_stop_times.R @@ -131,7 +131,7 @@ interpolate_stop_times <- function( # times after midnight written as early morning times are fixed first, so # they don't go back. the returned feed keeps the fixed times - gtfs <- fix_overnight_in_call(gtfs) + gtfs <- fix_overnight_in_call(gtfs = gtfs) stop_times <- gtfs$stop_times diff --git a/R/set_dwell_time.R b/R/set_dwell_time.R index d5f7dbeb..0f2a83d2 100644 --- a/R/set_dwell_time.R +++ b/R/set_dwell_time.R @@ -254,7 +254,7 @@ change_dwell_times <- function( # keeps them fixed gtfs$stop_times <- stop_times - gtfs <- fix_overnight_in_call(gtfs, by_reference = TRUE) + gtfs <- fix_overnight_in_call(gtfs = gtfs, by_reference = TRUE) selected_rows <- select_dwell_time_calls(stop_times, trip_id, stop_id) diff --git a/R/set_max_speed.R b/R/set_max_speed.R index b00f6625..ceb73c12 100644 --- a/R/set_max_speed.R +++ b/R/set_max_speed.R @@ -200,7 +200,7 @@ limit_trip_speed <- function( # times after midnight written as early morning times are fixed first, so # they don't go back. the returned feed keeps the fixed times - gtfs <- fix_overnight_in_call(gtfs) + gtfs <- fix_overnight_in_call(gtfs = gtfs) # select the trips. ids is NULL only when both arguments are NULL, so that # trip_ids that don't exist don't result in all trips being changed diff --git a/R/set_min_speed.R b/R/set_min_speed.R index bcad566a..e555c32e 100644 --- a/R/set_min_speed.R +++ b/R/set_min_speed.R @@ -42,9 +42,9 @@ #' `"00:30:00"` instead of `"24:30:00"`) are first fixed with #' [fix_overnight_times()] in every trip, so the returned GTFS has them fixed. #' Spans whose arrival is still earlier than the previous departure (by 12 -#' hours or less) are left unchanged, with a warning. An error is raised if a shift would result -#' in a time earlier than `"00:00:00"`. Only `stop_times` is modified; its -#' existing `_secs` columns are updated to match. +#' hours or less) are left unchanged, with a warning. An error is raised if a +#' shift would result in a time earlier than `"00:00:00"`. Only `stop_times` +#' is modified; its existing `_secs` columns are updated to match. #' #' With `first_stop` and `last_stop`, matched as in [set_trip_speed()], only #' the spans between them are raised: times before `first_stop` don't change, diff --git a/R/set_route_frequency.R b/R/set_route_frequency.R index a71b4416..1371b738 100644 --- a/R/set_route_frequency.R +++ b/R/set_route_frequency.R @@ -151,7 +151,7 @@ set_route_frequency <- function(gtfs, # the departures and the clipped 'frequencies' entries below use the same # times. the returned feed keeps them fixed - gtfs <- fix_overnight_in_call(gtfs, frequencies = TRUE) + gtfs <- fix_overnight_in_call(gtfs = gtfs, frequencies = TRUE) # select the trips of the relevant routes and raise warning if a given # route_id doesn't exist in 'trips'. the departures are grouped by route, diff --git a/R/set_trip_speed.R b/R/set_trip_speed.R index f789ce10..612b1487 100644 --- a/R/set_trip_speed.R +++ b/R/set_trip_speed.R @@ -269,7 +269,7 @@ set_trip_speed <- function( # keeps them fixed gtfs$stop_times <- stop_times - gtfs <- fix_overnight_in_call(gtfs, by_reference = TRUE) + gtfs <- fix_overnight_in_call(gtfs = gtfs, by_reference = TRUE) # select the rows of the given trips, ordered as in get_trip_length(), so # that the segment starting at the n-th stop of a trip is its n-th segment. diff --git a/man/set_min_speed.Rd b/man/set_min_speed.Rd index d0c434e6..498db69e 100644 --- a/man/set_min_speed.Rd +++ b/man/set_min_speed.Rd @@ -84,9 +84,9 @@ kept. Times after midnight written as early morning times (e.g. \code{"00:30:00"} instead of \code{"24:30:00"}) are first fixed with \code{\link[=fix_overnight_times]{fix_overnight_times()}} in every trip, so the returned GTFS has them fixed. Spans whose arrival is still earlier than the previous departure (by 12 -hours or less) are left unchanged, with a warning. An error is raised if a shift would result -in a time earlier than \code{"00:00:00"}. Only \code{stop_times} is modified; its -existing \verb{_secs} columns are updated to match. +hours or less) are left unchanged, with a warning. An error is raised if a +shift would result in a time earlier than \code{"00:00:00"}. Only \code{stop_times} +is modified; its existing \verb{_secs} columns are updated to match. With \code{first_stop} and \code{last_stop}, matched as in \code{\link[=set_trip_speed]{set_trip_speed()}}, only the spans between them are raised: times before \code{first_stop} don't change, diff --git a/tests/testthat/setup-overnight_feed.R b/tests/testthat/setup-overnight_feed.R index 04a33d50..5b54e280 100644 --- a/tests/testthat/setup-overnight_feed.R +++ b/tests/testthat/setup-overnight_feed.R @@ -34,5 +34,5 @@ overnight_feed <- function() { ) ) - return(gtfsio::new_gtfs(feed, "dt_gtfs")) + return(value = gtfsio::new_gtfs(x = feed, subclass = "dt_gtfs")) } diff --git a/tests/testthat/test-build_graph.R b/tests/testthat/test-build_graph.R index b2555cbc..e4e3707d 100644 --- a/tests/testthat/test-build_graph.R +++ b/tests/testthat/test-build_graph.R @@ -378,8 +378,16 @@ test_that("handles times after midnight and decreasing times", { ), stop_times = rbind( new_stop_times("P1", c("A", "B"), c("24:30:00", "24:35:00")), - new_stop_times("W1", c("A", "B"), c("23:58:00", "00:02:00")), - new_stop_times("D1", c("A", "B"), c("08:02:00", "07:58:00")) + new_stop_times( + trip_id = "W1", + stop_id = c("A", "B"), + arrival_time = c("23:58:00", "00:02:00") + ), + new_stop_times( + trip_id = "D1", + stop_id = c("A", "B"), + arrival_time = c("08:02:00", "07:58:00") + ) ) ) @@ -391,23 +399,23 @@ test_that("handles times after midnight and decreasing times", { # W1 is written going back to 00:02 after midnight, which is fixed to # 24:02 first, so it departs at 23:58 and runs at night - night_graph <- tester(gtfs, from = "23:00:00", to = "24:00:00") + night_graph <- tester(gtfs = gtfs, from = "23:00:00", to = "24:00:00") in_vehicle <- night_graph$link[link_type == "in_vehicle"] - expect_identical(in_vehicle$route_id, "R2") - expect_equal(in_vehicle$travel_time, 4) + expect_identical(object = in_vehicle$route_id, expected = "R2") + expect_equal(object = in_vehicle$travel_time, expected = 4) - early_graph <- tester(gtfs, from = "00:00:00", to = "01:00:00") - expect_false("R2" %chin% early_graph$link$route_id) + early_graph <- tester(gtfs = gtfs, from = "00:00:00", to = "01:00:00") + expect_false(object = "R2" %chin% early_graph$link$route_id) # D1 goes back by less than 12 hours, so it departs at its earliest time # and its segment has no travel time expect_warning( - day_graph <- tester(gtfs, from = "07:00:00", to = "09:00:00"), + day_graph <- tester(gtfs = gtfs, from = "07:00:00", to = "09:00:00"), class = "gtfstools_links_without_travel_time" ) in_vehicle <- day_graph$link[link_type == "in_vehicle"] - expect_identical(in_vehicle$route_id, "R3") + expect_identical(object = in_vehicle$route_id, expected = "R3") expect_identical(in_vehicle$travel_time, NA_real_) expect_identical(in_vehicle$free_speed, NA_real_) @@ -420,9 +428,9 @@ test_that("handles times after midnight and decreasing times", { end_time = "01:00:00", headway_secs = 600L ) - night_graph <- tester(gtfs, from = "23:00:00", to = "24:00:00") + night_graph <- tester(gtfs = gtfs, from = "23:00:00", to = "24:00:00") in_vehicle <- night_graph$link[link_type == "in_vehicle" & route_id == "R1"] - expect_identical(in_vehicle$departures, 6L) + expect_identical(object = in_vehicle$departures, expected = 6L) }) test_that("uses the first entry of duplicated trip_ids", { diff --git a/tests/testthat/test-filter_by_time_of_day.R b/tests/testthat/test-filter_by_time_of_day.R index 5de6c716..b09e4c8a 100644 --- a/tests/testthat/test-filter_by_time_of_day.R +++ b/tests/testthat/test-filter_by_time_of_day.R @@ -532,20 +532,34 @@ test_that("handles trips with some non specified departure/arrival times", { expect_identical(filtered_stop_times, gtfs$stop_times) }) -test_that("fixes times after midnight written as early morning times", { - gtfs <- overnight_feed() - original_stop_times <- data.table::copy(gtfs$stop_times) +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + gtfs <- overnight_feed() + original_stop_times <- data.table::copy(x = gtfs$stop_times) - result <- filter_by_time_of_day(gtfs, "23:00:00", "25:00:00") - expect_identical( - result$stop_times[trip_id == "W"]$arrival_time, - c("23:50:00", "24:05:00", "24:20:00", "24:35:00") - ) - expect_identical(result$frequencies$end_time, "25:00:00") + result <- filter_by_time_of_day( + gtfs = gtfs, + from = "23:00:00", + to = "25:00:00" + ) + expect_identical( + object = result$stop_times[trip_id == "W"]$arrival_time, + expected = c("23:50:00", "24:05:00", "24:20:00", "24:35:00") + ) + expect_identical( + object = result$frequencies$end_time, + expected = "25:00:00" + ) - # W's stops after midnight are not within these times of day + # W's stops after midnight are not within these times of day - result <- filter_by_time_of_day(gtfs, "00:00:00", "01:00:00") - expect_false("W" %chin% result$stop_times$trip_id) - expect_identical(gtfs$stop_times, original_stop_times) -}) + result <- filter_by_time_of_day( + gtfs = gtfs, + from = "00:00:00", + to = "01:00:00" + ) + expect_false(object = "W" %chin% result$stop_times$trip_id) + expect_identical(object = gtfs$stop_times, expected = original_stop_times) + } +) diff --git a/tests/testthat/test-fix_gtfs.R b/tests/testthat/test-fix_gtfs.R index 31e76c57..f53ec1ab 100644 --- a/tests/testthat/test-fix_gtfs.R +++ b/tests/testthat/test-fix_gtfs.R @@ -230,7 +230,7 @@ test_that("fills shape_dist_traveled, only in feeds with shapes", { expect_false("shape_dist_traveled" %chin% names(result$stop_times)) }) -test_that("fixes the times of trips that run past midnight", { +test_that(desc = "fixes the times of trips that run past midnight", code = { # some trips of this feed have times after midnight written as "00:xx:xx". # they are fixed first, so their times are then capped and interpolated @@ -247,25 +247,28 @@ test_that("fixes the times of trips that run past midnight", { invokeRestart("muffleWarning") } ) - expect_false("gtfstools_backwards_times" %in% warning_classes) + expect_false(object = "gtfstools_backwards_times" %in% warning_classes) # the trip keeps its start time and ends after midnight. its intermediate # times are filled, and depend on the capped speeds, so only their order is # checked trip_times <- result$stop_times[trip_id == trip][order(stop_sequence)] - expect_identical(trip_times$arrival_time[1], "23:10:00") - expect_true(all(trip_times$arrival_time != "")) - expect_true(all(trip_times$departure_time != "")) + expect_identical(object = trip_times$arrival_time[1], expected = "23:10:00") + expect_true(object = all(trip_times$arrival_time != "")) + expect_true(object = all(trip_times$departure_time != "")) secs <- as.vector( - rbind( - string_to_seconds(trip_times$arrival_time), - string_to_seconds(trip_times$departure_time) + x = rbind( + string_to_seconds(string = trip_times$arrival_time), + string_to_seconds(string = trip_times$departure_time) ) ) - expect_false(is.unsorted(secs)) - expect_gte(secs[length(secs)], string_to_seconds("24:02:00")) + expect_false(object = is.unsorted(x = secs)) + expect_gte( + object = secs[length(x = secs)], + expected = string_to_seconds(string = "24:02:00") + ) }) test_that("unit arguments work correctly", { diff --git a/tests/testthat/test-fix_overnight_times.R b/tests/testthat/test-fix_overnight_times.R index 98f61526..941d5b31 100644 --- a/tests/testthat/test-fix_overnight_times.R +++ b/tests/testthat/test-fix_overnight_times.R @@ -1,36 +1,36 @@ spo_path <- system.file("extdata/spo_gtfs.zip", package = "gtfstools") poa_path <- system.file("extdata/poa_gtfs.zip", package = "gtfstools") -tester <- function(gtfs = wrap_gtfs) fix_overnight_times(gtfs) +tester <- function(gtfs = wrap_gtfs) fix_overnight_times(gtfs = gtfs) # creates a feed with one trip per element of 'times', a named list with the # arrival and departure times of each trip (departures default to arrivals) synthetic_feed <- function(times) { stop_times <- data.table::rbindlist( - lapply( - names(times), - function(id) { + l = lapply( + X = names(x = times), + FUN = function(id) { arr <- times[[id]]$arr dep <- times[[id]]$dep - if (is.null(dep)) dep <- arr + if (is.null(x = dep)) dep <- arr data.table::data.table( trip_id = id, arrival_time = arr, departure_time = dep, - stop_id = paste0("s", seq_along(arr)), - stop_sequence = seq_along(arr) + stop_id = paste0("s", seq_along(along.with = arr)), + stop_sequence = seq_along(along.with = arr) ) } ) ) feed <- list( - trips = data.table::data.table(trip_id = names(times), route_id = "r1"), + trips = data.table::data.table(trip_id = names(x = times), route_id = "r1"), stop_times = stop_times ) - return(gtfsio::new_gtfs(feed, "dt_gtfs")) + return(value = gtfsio::new_gtfs(x = feed, subclass = "dt_gtfs")) } # trips that run past midnight, with the times they should have after the fix @@ -81,7 +81,7 @@ expected_times <- list( daytime = wrap_times$daytime ) -wrap_gtfs <- synthetic_feed(wrap_times) +wrap_gtfs <- synthetic_feed(times = wrap_times) wrap_gtfs$frequencies <- data.table::data.table( trip_id = "correct", start_time = c("23:00:00", "05:00:00", "22:00:00", "48:30:00", "25:00:00"), @@ -92,7 +92,7 @@ wrap_gtfs$frequencies <- data.table::data.table( # trips whose times still go back after the fix, which raise a warning warn_gtfs <- synthetic_feed( - list( + times = list( small_back = list(arr = c("08:00:00", "08:05:00", "08:04:00")), exactly_12h = list(arr = c("20:00:00", "08:00:00")), back_after_fix = list(arr = c("24:30:00", "00:20:00")) @@ -101,161 +101,193 @@ warn_gtfs <- synthetic_feed( trip_times <- function(gtfs, id) { st <- gtfs$stop_times[trip_id == id] - return(list(arr = st$arrival_time, dep = st$departure_time)) + return(value = list(arr = st$arrival_time, dep = st$departure_time)) } expect_trip_times <- function(gtfs, id, expected) { - if (is.null(expected$dep)) expected$dep <- expected$arr - expect_identical(trip_times(gtfs, id), expected[c("arr", "dep")]) + if (is.null(x = expected$dep)) expected$dep <- expected$arr + expect_identical( + object = trip_times(gtfs = gtfs, id = id), + expected = expected[c("arr", "dep")] + ) } # tests --- -test_that("raises error due to incorrect input types", { - expect_error(tester(unclass(wrap_gtfs))) +test_that(desc = "raises error due to incorrect input types", code = { + expect_error(object = tester(gtfs = unclass(x = wrap_gtfs))) - no_arrival <- copy_gtfs_without_field(wrap_gtfs, "stop_times", "arrival_time") - expect_error(tester(no_arrival)) + no_arrival <- copy_gtfs_without_field( + gtfs = wrap_gtfs, + file = "stop_times", + field = "arrival_time" + ) + expect_error(object = tester(gtfs = no_arrival)) bad_sequence <- copy_gtfs_diff_field_class( - wrap_gtfs, - "stop_times", - "stop_sequence", - "character" + gtfs = wrap_gtfs, + file = "stop_times", + field = "stop_sequence", + class = "character" ) - expect_error(tester(bad_sequence)) + expect_error(object = tester(gtfs = bad_sequence)) bad_end <- copy_gtfs_diff_field_class( - wrap_gtfs, - "frequencies", - "end_time", - "factor" + gtfs = wrap_gtfs, + file = "frequencies", + field = "end_time", + class = "factor" ) - expect_error(tester(bad_end)) + expect_error(object = tester(gtfs = bad_end)) - expect_error(tester(copy_gtfs_without_file(wrap_gtfs, "stop_times"))) + expect_error( + object = tester( + gtfs = copy_gtfs_without_file(gtfs = wrap_gtfs, file = "stop_times") + ) + ) }) -test_that("results in a dt_gtfs object", { +test_that(desc = "results in a dt_gtfs object", code = { result <- tester() - expect_s3_class(result, c("dt_gtfs", "gtfs", "list")) - for (table in names(result)) { - expect_s3_class(result[[table]], "data.table") + expect_s3_class(object = result, class = c("dt_gtfs", "gtfs", "list")) + for (table in names(x = result)) { + expect_s3_class(object = result[[table]], class = "data.table") } }) -test_that("moves the times after midnight one day later", { - result <- expect_silent(tester()) +test_that(desc = "moves the times after midnight one day later", code = { + result <- expect_silent(object = tester()) - for (id in names(expected_times)) { - expect_trip_times(result, id, expected_times[[id]]) + for (id in names(x = expected_times)) { + expect_trip_times(gtfs = result, id = id, expected = expected_times[[id]]) } # only the time columns change expect_identical( - result$stop_times[, .(trip_id, stop_id, stop_sequence)], - wrap_gtfs$stop_times[, .(trip_id, stop_id, stop_sequence)] + object = result$stop_times[, .(trip_id, stop_id, stop_sequence)], + expected = wrap_gtfs$stop_times[, .(trip_id, stop_id, stop_sequence)] ) - expect_identical(result$trips, wrap_gtfs$trips) + expect_identical(object = result$trips, expected = wrap_gtfs$trips) }) -test_that("leaves rows without trip_id or stop_sequence unchanged", { - gtfs <- wrap_gtfs - gtfs$stop_times <- rbind( - wrap_gtfs$stop_times, - data.table::data.table( - trip_id = c(NA, "arrival"), - arrival_time = "00:05:00", - departure_time = "00:05:00", - stop_id = "s1", - stop_sequence = c(10L, NA) +test_that( + desc = "leaves rows without trip_id or stop_sequence unchanged", + code = { + gtfs <- wrap_gtfs + gtfs$stop_times <- rbind( + wrap_gtfs$stop_times, + data.table::data.table( + trip_id = c(NA, "arrival"), + arrival_time = "00:05:00", + departure_time = "00:05:00", + stop_id = "s1", + stop_sequence = c(10L, NA) + ) ) - ) - result <- tester(gtfs) - expect_identical( - result$stop_times[is.na(trip_id) | is.na(stop_sequence), arrival_time], - c("00:05:00", "00:05:00") - ) - expect_trip_times( - result, - "arrival", - list(arr = c("23:00:00", "23:50:00", "24:10:00", "00:05:00")) - ) -}) + result <- tester(gtfs = gtfs) + expect_identical( + object = result$stop_times[ + is.na(x = trip_id) | is.na(x = stop_sequence), + arrival_time + ], + expected = c("00:05:00", "00:05:00") + ) + expect_trip_times( + gtfs = result, + id = "arrival", + expected = list(arr = c("23:00:00", "23:50:00", "24:10:00", "00:05:00")) + ) + } +) -test_that("warns about times that still go back", { +test_that(desc = "warns about times that still go back", code = { expect_warning( - result <- tester(warn_gtfs), + object = result <- tester(gtfs = warn_gtfs), class = "gtfstools_backwards_times" ) expect_trip_times( - result, - "small_back", - list(arr = c("08:00:00", "08:05:00", "08:04:00")) + gtfs = result, + id = "small_back", + expected = list(arr = c("08:00:00", "08:05:00", "08:04:00")) ) expect_trip_times( - result, - "exactly_12h", - list(arr = c("20:00:00", "08:00:00")) + gtfs = result, + id = "exactly_12h", + expected = list(arr = c("20:00:00", "08:00:00")) ) expect_trip_times( - result, - "back_after_fix", - list(arr = c("24:30:00", "24:20:00")) + gtfs = result, + id = "back_after_fix", + expected = list(arr = c("24:30:00", "24:20:00")) ) # every trip is named in the warning warning_msg <- tryCatch( - tester(warn_gtfs), - warning = function(w) conditionMessage(w) + expr = tester(gtfs = warn_gtfs), + warning = function(w) conditionMessage(c = w) ) for (id in c("small_back", "exactly_12h", "back_after_fix")) { - expect_match(warning_msg, id, fixed = TRUE) + expect_match(object = warning_msg, regexp = id, fixed = TRUE) } }) -test_that("fixes end times earlier than start times in frequencies", { - result <- tester() - expect_identical( - result$frequencies$end_time, - c("25:00:00", "06:00:00", "24:30:00", "72:10:00", "49:00:00") - ) - expect_identical( - result$frequencies$start_time, - wrap_gtfs$frequencies$start_time - ) +test_that( + desc = "fixes end times earlier than start times in frequencies", + code = { + result <- tester() + expect_identical( + object = result$frequencies$end_time, + expected = c("25:00:00", "06:00:00", "24:30:00", "72:10:00", "49:00:00") + ) + expect_identical( + object = result$frequencies$start_time, + expected = wrap_gtfs$frequencies$start_time + ) - no_frequencies <- copy_gtfs_without_file(wrap_gtfs, "frequencies") - result <- tester(no_frequencies) - expect_null(result$frequencies) - expect_trip_times(result, "arrival", expected_times$arrival) -}) + no_frequencies <- copy_gtfs_without_file( + gtfs = wrap_gtfs, + file = "frequencies" + ) + result <- tester(gtfs = no_frequencies) + expect_null(object = result$frequencies) + expect_trip_times( + gtfs = result, + id = "arrival", + expected = expected_times$arrival + ) + } +) -test_that("updates existing _secs columns", { - gtfs <- convert_time_to_seconds(wrap_gtfs) - result <- tester(gtfs) +test_that(desc = "updates existing _secs columns", code = { + gtfs <- convert_time_to_seconds(gtfs = wrap_gtfs) + result <- tester(gtfs = gtfs) expect_identical( - result$stop_times$arrival_time_secs, - string_to_seconds(result$stop_times$arrival_time) + object = result$stop_times$arrival_time_secs, + expected = string_to_seconds(string = result$stop_times$arrival_time) ) expect_identical( - result$stop_times$departure_time_secs, - string_to_seconds(result$stop_times$departure_time) + object = result$stop_times$departure_time_secs, + expected = string_to_seconds(string = result$stop_times$departure_time) ) expect_identical( - result$frequencies$end_time_secs, - string_to_seconds(result$frequencies$end_time) + object = result$frequencies$end_time_secs, + expected = string_to_seconds(string = result$frequencies$end_time) ) }) -test_that("raises an error when a fixed time is out of range", { - gtfs <- synthetic_feed(list(late = list(arr = c("9999:00:00", "00:10:00")))) - expect_error(tester(gtfs), class = "gtfstools_time_out_of_range") +test_that(desc = "raises an error when a fixed time is out of range", code = { + gtfs <- synthetic_feed( + times = list(late = list(arr = c("9999:00:00", "00:10:00"))) + ) + expect_error( + object = tester(gtfs = gtfs), + class = "gtfstools_time_out_of_range" + ) gtfs <- wrap_gtfs gtfs$frequencies <- data.table::data.table( @@ -264,84 +296,108 @@ test_that("raises an error when a fixed time is out of range", { end_time = "9990:00:00", headway_secs = 600L ) - expect_error(tester(gtfs), class = "gtfstools_time_out_of_range") + expect_error( + object = tester(gtfs = gtfs), + class = "gtfstools_time_out_of_range" + ) }) -test_that("doesn't change given gtfs", { +test_that(desc = "doesn't change given gtfs", code = { original_gtfs <- gtfsio::new_gtfs( - lapply(wrap_gtfs, data.table::copy), - "dt_gtfs" + x = lapply(X = wrap_gtfs, FUN = data.table::copy), + subclass = "dt_gtfs" + ) + gtfs <- gtfsio::new_gtfs( + x = lapply(X = wrap_gtfs, FUN = data.table::copy), + subclass = "dt_gtfs" ) - gtfs <- gtfsio::new_gtfs(lapply(wrap_gtfs, data.table::copy), "dt_gtfs") - expect_identical(original_gtfs, gtfs) + expect_identical(object = original_gtfs, expected = gtfs) - result <- tester(gtfs) - expect_false(identical(result$stop_times, gtfs$stop_times)) - expect_false(identical(result$frequencies, gtfs$frequencies)) - expect_equal(original_gtfs, gtfs, ignore_attr = TRUE) + result <- tester(gtfs = gtfs) + expect_false(object = identical(x = result$stop_times, y = gtfs$stop_times)) + expect_false(object = identical(x = result$frequencies, y = gtfs$frequencies)) + expect_equal(object = original_gtfs, expected = gtfs, ignore_attr = TRUE) - original_gtfs <- read_gtfs(poa_path) - gtfs <- read_gtfs(poa_path) - expect_identical(original_gtfs, gtfs) + original_gtfs <- read_gtfs(path = poa_path) + gtfs <- read_gtfs(path = poa_path) + expect_identical(object = original_gtfs, expected = gtfs) - result <- tester(gtfs) - expect_false(identical(result$stop_times, gtfs$stop_times)) - expect_equal(original_gtfs, gtfs, ignore_attr = TRUE) + result <- tester(gtfs = gtfs) + expect_false(object = identical(x = result$stop_times, y = gtfs$stop_times)) + expect_equal(object = original_gtfs, expected = gtfs, ignore_attr = TRUE) }) -test_that("returns feeds without times after midnight unchanged", { - spo_gtfs <- read_gtfs(spo_path) - result <- expect_silent(tester(spo_gtfs)) - expect_identical(result, spo_gtfs) -}) +test_that( + desc = "returns feeds without times after midnight unchanged", + code = { + spo_gtfs <- read_gtfs(path = spo_path) + result <- expect_silent(object = tester(gtfs = spo_gtfs)) + expect_identical(object = result, expected = spo_gtfs) + } +) -test_that("fixes the trips of poa that run past midnight", { - poa_gtfs <- read_gtfs(poa_path) - result <- expect_silent(tester(poa_gtfs)) +test_that(desc = "fixes the trips of poa that run past midnight", code = { + poa_gtfs <- read_gtfs(path = poa_path) + result <- expect_silent(object = tester(gtfs = poa_gtfs)) changed <- result$stop_times$arrival_time != poa_gtfs$stop_times$arrival_time - expect_length(unique(result$stop_times$trip_id[changed]), 10) + expect_length(object = unique(x = result$stop_times$trip_id[changed]), n = 10) expect_trip_times( - result, - "T2-1@1#2310", - list( - arr = c("23:10:00", rep("", 60), "24:02:00"), - dep = c("23:10:00", rep("", 60), "24:02:00") + gtfs = result, + id = "T2-1@1#2310", + expected = list( + arr = c("23:10:00", rep(x = "", 60), "24:02:00"), + dep = c("23:10:00", rep(x = "", 60), "24:02:00") ) ) }) -test_that("the internal fix can be restricted to some trips", { - result <- fix_overnight_stop_times(wrap_gtfs, trip_id = "arrival") - expect_trip_times(result, "arrival", expected_times$arrival) - expect_trip_times(result, "arr_dep", wrap_times$arr_dep) +test_that(desc = "the internal fix can be restricted to some trips", code = { + result <- fix_overnight_stop_times(gtfs = wrap_gtfs, trip_id = "arrival") + expect_trip_times( + gtfs = result, + id = "arrival", + expected = expected_times$arrival + ) + expect_trip_times( + gtfs = result, + id = "arr_dep", + expected = wrap_times$arr_dep + ) # with shuffled rows and an unknown id, the selected trips are fixed as when # every trip is fixed, and the others are left unchanged shuffled_gtfs <- wrap_gtfs shuffled_gtfs$stop_times <- wrap_gtfs$stop_times[ - rev(seq_len(nrow(wrap_gtfs$stop_times))) + rev(x = seq_len(length.out = nrow(x = wrap_gtfs$stop_times))) ] selected <- c("one_time", "double_wrap", "unknown") - result <- fix_overnight_stop_times(shuffled_gtfs, trip_id = selected) + result <- fix_overnight_stop_times(gtfs = shuffled_gtfs, trip_id = selected) for (id in c("one_time", "double_wrap")) { - expect_trip_times(result, id, lapply(expected_times[[id]], rev)) + expect_trip_times( + gtfs = result, + id = id, + expected = lapply(X = expected_times[[id]], FUN = rev) + ) } expect_identical( - result$stop_times[!trip_id %chin% selected], - shuffled_gtfs$stop_times[!trip_id %chin% selected] + object = result$stop_times[!trip_id %chin% selected], + expected = shuffled_gtfs$stop_times[!trip_id %chin% selected] ) expect_identical( - fix_overnight_stop_times(wrap_gtfs, trip_id = character(0)), - wrap_gtfs + object = fix_overnight_stop_times( + gtfs = wrap_gtfs, + trip_id = character(length = 0) + ), + expected = wrap_gtfs ) }) -test_that("nested calls don't fix the times again", { - poa_gtfs <- read_gtfs(poa_path) +test_that(desc = "nested calls don't fix the times again", code = { + poa_gtfs <- read_gtfs(path = poa_path) # only the runs that change some time are counted, which is checked before # each run, since tables fixed by reference look the same afterwards @@ -357,54 +413,80 @@ test_that("nested calls don't fix the times again", { detect_only = FALSE ) { if (!detect_only) { - changes <- real_fix(gtfs, trip_id, warn = FALSE, detect_only = TRUE) - if (isTRUE(changes)) n_fixes <<- n_fixes + 1 + changes <- real_fix( + gtfs = gtfs, + trip_id = trip_id, + warn = FALSE, + detect_only = TRUE + ) + if (isTRUE(x = changes)) n_fixes <<- n_fixes + 1 } - real_fix(gtfs, trip_id, warn, by_reference, detect_only) + real_fix( + gtfs = gtfs, + trip_id = trip_id, + warn = warn, + by_reference = by_reference, + detect_only = detect_only + ) } ) count_fixes <- function(expr) { n_fixes <<- 0 - force(expr) - return(n_fixes) + force(x = expr) + return(value = n_fixes) } - expect_identical(count_fixes(fix_gtfs(poa_gtfs)), 1) expect_identical( - count_fixes(get_trip_speed(poa_gtfs, from = "07:00:00", to = "09:00:00")), - 1 + object = count_fixes(expr = fix_gtfs(gtfs = poa_gtfs)), + expected = 1 + ) + expect_identical( + object = count_fixes( + expr = get_trip_speed(gtfs = poa_gtfs, from = "07:00:00", to = "09:00:00") + ), + expected = 1 ) expect_identical( - count_fixes( - suppressWarnings( - build_graph(poa_gtfs, from = "07:00:00", to = "08:00:00") + object = count_fixes( + expr = suppressWarnings( + expr = build_graph(gtfs = poa_gtfs, from = "07:00:00", to = "08:00:00") ) ), - 1 + expected = 1 ) expect_identical( - count_fixes( - get_stop_frequency(poa_gtfs, from = "07:00:00", to = "08:00:00") + object = count_fixes( + expr = get_stop_frequency( + gtfs = poa_gtfs, + from = "07:00:00", + to = "08:00:00" + ) ), - 1 + expected = 1 ) if (report_deps_available()) { expect_identical( - count_fixes( - get_summary( - poa_gtfs, - output_path = tempfile("get_summary"), + object = count_fixes( + expr = get_summary( + gtfs = poa_gtfs, + output_path = tempfile(pattern = "get_summary"), html_preview = FALSE ) ), - 1 + expected = 1 ) } - by_reference_gtfs <- read_gtfs(poa_path) + by_reference_gtfs <- read_gtfs(path = poa_path) expect_identical( - count_fixes(set_dwell_time(by_reference_gtfs, 30, by_reference = TRUE)), - 1 + object = count_fixes( + expr = set_dwell_time( + gtfs = by_reference_gtfs, + dwell_time = 30, + by_reference = TRUE + ) + ), + expected = 1 ) # a function called by the user while a call is in progress (e.g. in a @@ -413,82 +495,110 @@ test_that("nested calls don't fix the times again", { gtfs <- overnight_feed() duration <- NULL withCallingHandlers( - get_trip_duration(gtfs, c("W", "unknown")), + expr = get_trip_duration(gtfs = gtfs, trip_id = c("W", "unknown")), warning = function(w) { - duration <<- get_trip_duration(gtfs, "W")$duration - invokeRestart("muffleWarning") + duration <<- get_trip_duration(gtfs = gtfs, trip_id = "W")$duration + invokeRestart(r = "muffleWarning") } ) - expect_equal(duration, 45) + expect_equal(object = duration, expected = 45) gtfs <- overnight_feed() gtfs$frequencies[, `:=`(start_time = "9999:00:00", end_time = "9990:00:00")] expect_error( - get_route_frequency(gtfs, from = "23:00:00", to = "24:00:00"), + object = get_route_frequency( + gtfs = gtfs, + from = "23:00:00", + to = "24:00:00" + ), class = "gtfstools_time_out_of_range" ) }) -test_that("has_overnight_trips() detects the times that would be fixed", { - expect_true(has_overnight_trips(read_gtfs(poa_path))) - expect_true(has_overnight_trips(wrap_gtfs)) - expect_true(has_overnight_trips(overnight_feed())) +test_that( + desc = "has_overnight_trips() detects the times that would be fixed", + code = { + expect_true(object = has_overnight_trips(gtfs = read_gtfs(path = poa_path))) + expect_true(object = has_overnight_trips(gtfs = wrap_gtfs)) + expect_true(object = has_overnight_trips(gtfs = overnight_feed())) - # feeds without them, or whose times were already fixed + # feeds without them, or whose times were already fixed - expect_false(has_overnight_trips(read_gtfs(spo_path))) - expect_false(has_overnight_trips(fix_overnight_times(read_gtfs(poa_path)))) - expect_false(has_overnight_trips(fix_overnight_times(overnight_feed()))) + expect_false( + object = has_overnight_trips(gtfs = read_gtfs(path = spo_path)) + ) + expect_false( + object = has_overnight_trips( + gtfs = fix_overnight_times(gtfs = read_gtfs(path = poa_path)) + ) + ) + expect_false( + object = has_overnight_trips( + gtfs = fix_overnight_times(gtfs = overnight_feed()) + ) + ) - # times that go back by 12 hours or less are not fixed, so they don't count + # times that go back by 12 hours or less are not fixed, so they don't count - small_steps <- synthetic_feed( - list( - small_back = list(arr = c("08:00:00", "08:05:00", "08:04:00")), - exactly_12h = list(arr = c("20:00:00", "08:00:00")) + small_steps <- synthetic_feed( + times = list( + small_back = list(arr = c("08:00:00", "08:05:00", "08:04:00")), + exactly_12h = list(arr = c("20:00:00", "08:00:00")) + ) ) - ) - expect_silent(result <- has_overnight_trips(small_steps)) - expect_false(result) + expect_silent(object = result <- has_overnight_trips(gtfs = small_steps)) + expect_false(object = result) - # only frequencies entries that end before they start + # only frequencies entries that end before they start - gtfs <- fix_overnight_times(overnight_feed()) - gtfs$frequencies$end_time <- "01:00:00" - expect_true(has_overnight_trips(gtfs)) + gtfs <- fix_overnight_times(gtfs = overnight_feed()) + gtfs$frequencies$end_time <- "01:00:00" + expect_true(object = has_overnight_trips(gtfs = gtfs)) - # tables that can't be checked are skipped + # tables that can't be checked are skipped - no_sequence <- copy_gtfs_without_field( - overnight_feed(), - "stop_times", - "stop_sequence" - ) - no_sequence$frequencies <- NULL - expect_false(has_overnight_trips(no_sequence)) -}) + no_sequence <- copy_gtfs_without_field( + gtfs = overnight_feed(), + file = "stop_times", + field = "stop_sequence" + ) + no_sequence$frequencies <- NULL + expect_false(object = has_overnight_trips(gtfs = no_sequence)) + } +) -test_that("warns about times that go back in feeds without times to fix", { - # the feed has no times after midnight to fix, but its times that go back - # by 12 hours or less, and its malformed times, are still reported +test_that( + desc = "warns about times that go back in feeds without times to fix", + code = { + # the feed has no times after midnight to fix, but its times that go back + # by 12 hours or less, and its malformed times, are still reported - small_back <- synthetic_feed( - list(small_back = list(arr = c("08:00:00", "08:05:00", "08:04:00"))) - ) - expect_false(has_overnight_trips(small_back)) - expect_warning( - result <- tester(small_back), - class = "gtfstools_backwards_times" - ) - expect_identical(result$stop_times, small_back$stop_times) + small_back <- synthetic_feed( + times = list( + small_back = list(arr = c("08:00:00", "08:05:00", "08:04:00")) + ) + ) + expect_false(object = has_overnight_trips(gtfs = small_back)) + expect_warning( + object = result <- tester(gtfs = small_back), + class = "gtfstools_backwards_times" + ) + expect_identical( + object = result$stop_times, + expected = small_back$stop_times + ) - malformed <- synthetic_feed( - list( - malformed = list( - arr = c("08:00:00", "ab:cd", "08:10:00"), - dep = c("08:00:00", "08:05:00", "08:10:00") + malformed <- synthetic_feed( + times = list( + malformed = list( + arr = c("08:00:00", "ab:cd", "08:10:00"), + dep = c("08:00:00", "08:05:00", "08:10:00") + ) ) ) - ) - expect_warning(tester(malformed), class = "gtfstools_malformed_time") -}) + expect_warning( + object = tester(gtfs = malformed), + class = "gtfstools_malformed_time" + ) + } +) diff --git a/tests/testthat/test-get_dwell_time.R b/tests/testthat/test-get_dwell_time.R index f0e56c83..cb64b415 100644 --- a/tests/testthat/test-get_dwell_time.R +++ b/tests/testthat/test-get_dwell_time.R @@ -221,37 +221,52 @@ test_that("only returns the visits that arrive within the time of day", { expect_vector(dwell$dwell_time, numeric(0)) }) -test_that("fixes times after midnight written as early morning times", { - # a trip whose times after midnight are written as early morning times, - # including the departure from its second stop - - overnight_gtfs <- gtfsio::new_gtfs( - list( - stop_times = data.table::data.table( - trip_id = "t1", - stop_id = c("s1", "s2", "s3"), - stop_sequence = 1:3, - arrival_time = c("23:50:00", "23:58:00", "00:05:00"), - departure_time = c("23:50:00", "00:01:00", "00:05:00") - ) - ), - "dt_gtfs" - ) - - original_gtfs <- gtfsio::new_gtfs( - lapply(overnight_gtfs, data.table::copy), - "dt_gtfs" - ) - - dwell <- tester(overnight_gtfs) - expect_equal(dwell$dwell_time, c(0, 180, 0)) - expect_equal(overnight_gtfs, original_gtfs, ignore_attr = TRUE) - - # the visits after midnight are compared with the time of day as fixed - - dwell <- get_dwell_time(overnight_gtfs, from = "00:00:00", to = "01:00:00") - expect_identical(nrow(dwell), 0L) - - dwell <- get_dwell_time(overnight_gtfs, from = "24:00:00", to = "25:00:00") - expect_identical(dwell$stop_id, "s3") -}) +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + # a trip whose times after midnight are written as early morning times, + # including the departure from its second stop + + overnight_gtfs <- gtfsio::new_gtfs( + x = list( + stop_times = data.table::data.table( + trip_id = "t1", + stop_id = c("s1", "s2", "s3"), + stop_sequence = 1:3, + arrival_time = c("23:50:00", "23:58:00", "00:05:00"), + departure_time = c("23:50:00", "00:01:00", "00:05:00") + ) + ), + subclass = "dt_gtfs" + ) + + original_gtfs <- gtfsio::new_gtfs( + x = lapply(X = overnight_gtfs, FUN = data.table::copy), + subclass = "dt_gtfs" + ) + + dwell <- tester(gtfs = overnight_gtfs) + expect_equal(object = dwell$dwell_time, expected = c(0, 180, 0)) + expect_equal( + object = overnight_gtfs, + expected = original_gtfs, + ignore_attr = TRUE + ) + + # the visits after midnight are compared with the time of day as fixed + + dwell <- get_dwell_time( + gtfs = overnight_gtfs, + from = "00:00:00", + to = "01:00:00" + ) + expect_identical(object = nrow(x = dwell), expected = 0L) + + dwell <- get_dwell_time( + gtfs = overnight_gtfs, + from = "24:00:00", + to = "25:00:00" + ) + expect_identical(object = dwell$stop_id, expected = "s3") + } +) diff --git a/tests/testthat/test-get_route_frequency.R b/tests/testthat/test-get_route_frequency.R index 16edfc65..4dc34007 100644 --- a/tests/testthat/test-get_route_frequency.R +++ b/tests/testthat/test-get_route_frequency.R @@ -317,38 +317,53 @@ test_that("doesn't change given gtfs", { expect_equal(original_gtfs, gtfs, ignore_attr = TRUE) }) -test_that("fixes times after midnight written as early morning times", { - # W departs at 23:50, and F every 30 minutes from 23:00 to "01:00:00" - - gtfs <- overnight_feed() - original_stop_times <- data.table::copy(gtfs$stop_times) - - result <- get_route_frequency(gtfs, from = "23:00:00", to = "24:00:00") - expect_identical(result$departures, c(1L, 2L)) - result <- get_route_frequency(gtfs, from = "24:00:00", to = "25:00:00") - expect_identical(result$route_id, "R2") - expect_identical(result$departures, 2L) - result <- get_route_frequency(gtfs, from = "00:00:00", to = "01:00:00") - expect_identical(nrow(result), 0L) - expect_identical(gtfs$stop_times, original_stop_times) +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + # W departs at 23:50, and F every 30 minutes from 23:00 to "01:00:00" + + gtfs <- overnight_feed() + original_stop_times <- data.table::copy(x = gtfs$stop_times) + + result <- get_route_frequency( + gtfs = gtfs, + from = "23:00:00", + to = "24:00:00" + ) + expect_identical(object = result$departures, expected = c(1L, 2L)) + result <- get_route_frequency( + gtfs = gtfs, + from = "24:00:00", + to = "25:00:00" + ) + expect_identical(object = result$route_id, expected = "R2") + expect_identical(object = result$departures, expected = 2L) + result <- get_route_frequency( + gtfs = gtfs, + from = "00:00:00", + to = "01:00:00" + ) + expect_identical(object = nrow(x = result), expected = 0L) + expect_identical(object = gtfs$stop_times, expected = original_stop_times) - # poa's trip departs at 23:10, not at its last time written as "00:02:00" + # poa's trip departs at 23:10, not at its last time written as "00:02:00" - poa_gtfs <- read_gtfs( - system.file("extdata/poa_gtfs.zip", package = "gtfstools") - ) - late <- get_route_frequency( - poa_gtfs, - "T2", - from = "23:00:00", - to = "23:59:59" - ) - early <- get_route_frequency( - poa_gtfs, - "T2", - from = "00:00:00", - to = "01:00:00" - ) - expect_gt(sum(late$departures), 0L) - expect_identical(sum(early$departures), 0L) -}) + poa_gtfs <- read_gtfs( + path = system.file("extdata/poa_gtfs.zip", package = "gtfstools") + ) + late <- get_route_frequency( + gtfs = poa_gtfs, + route_id = "T2", + from = "23:00:00", + to = "23:59:59" + ) + early <- get_route_frequency( + gtfs = poa_gtfs, + route_id = "T2", + from = "00:00:00", + to = "01:00:00" + ) + expect_gt(object = sum(late$departures), expected = 0L) + expect_identical(object = sum(early$departures), expected = 0L) + } +) diff --git a/tests/testthat/test-get_stop_frequency.R b/tests/testthat/test-get_stop_frequency.R index 33e6e965..b559de2c 100644 --- a/tests/testthat/test-get_stop_frequency.R +++ b/tests/testthat/test-get_stop_frequency.R @@ -443,32 +443,51 @@ test_that("doesn't change given gtfs", { expect_equal(original_gtfs, gtfs, ignore_attr = TRUE) }) -test_that("fixes times after midnight written as early morning times", { - # after midnight, F departs from A at 24:00 and 24:30, and W from B at 24:05 - # and C at 24:20 (D is W's last stop, and B is F's) - - gtfs <- overnight_feed() - original_stop_times <- data.table::copy(gtfs$stop_times) - - result <- get_stop_frequency(gtfs, from = "24:00:00", to = "25:00:00") - expect_identical(result$stop_id, c("A", "B", "C")) - expect_identical(result$departures, c(2L, 1L, 1L)) - - result <- get_stop_frequency( - gtfs, - stop_id = "B", - from = "24:00:00", - to = "25:00:00" - ) - expect_identical(result$departures, 1L) +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + # after midnight, F departs from A at 24:00 and 24:30, and W from B at 24:05 + # and C at 24:20 (D is W's last stop, and B is F's) + + gtfs <- overnight_feed() + original_stop_times <- data.table::copy(x = gtfs$stop_times) + + result <- get_stop_frequency( + gtfs = gtfs, + from = "24:00:00", + to = "25:00:00" + ) + expect_identical(object = result$stop_id, expected = c("A", "B", "C")) + expect_identical(object = result$departures, expected = c(2L, 1L, 1L)) + + result <- get_stop_frequency( + gtfs = gtfs, + stop_id = "B", + from = "24:00:00", + to = "25:00:00" + ) + expect_identical(object = result$departures, expected = 1L) - result <- get_stop_frequency(gtfs, from = "00:00:00", to = "01:00:00") - expect_identical(nrow(result), 0L) - expect_identical(gtfs$stop_times, original_stop_times) + result <- get_stop_frequency( + gtfs = gtfs, + from = "00:00:00", + to = "01:00:00" + ) + expect_identical(object = nrow(x = result), expected = 0L) + expect_identical(object = gtfs$stop_times, expected = original_stop_times) - # without arrival_time, the times can't be fixed and are used as written + # without arrival_time, the times can't be fixed and are used as written - no_arrival <- copy_gtfs_without_field(gtfs, "stop_times", "arrival_time") - result <- get_stop_frequency(no_arrival, from = "00:00:00", to = "01:00:00") - expect_identical(result$stop_id, c("B", "C")) -}) + no_arrival <- copy_gtfs_without_field( + gtfs = gtfs, + file = "stop_times", + field = "arrival_time" + ) + result <- get_stop_frequency( + gtfs = no_arrival, + from = "00:00:00", + to = "01:00:00" + ) + expect_identical(object = result$stop_id, expected = c("B", "C")) + } +) diff --git a/tests/testthat/test-get_trip_duration.R b/tests/testthat/test-get_trip_duration.R index 6cef696c..b8bd35c7 100644 --- a/tests/testthat/test-get_trip_duration.R +++ b/tests/testthat/test-get_trip_duration.R @@ -159,10 +159,10 @@ test_that("doesn't change given gtfs", { n_calls <- 0 testthat::local_mocked_bindings( - string_to_seconds = function(x) { + string_to_seconds = function(string) { n_calls <<- n_calls + 1 if (n_calls > 1) stop("interrupted") - return(rep(0L, length(x))) + return(value = rep(x = 0L, length(x = string))) } ) expect_error(tester(gtfs = new_gtfs), "interrupted") @@ -310,48 +310,61 @@ test_that("empty results have the same duration type as non-empty ones", { } }) -test_that("fixes times after midnight written as early morning times", { - # a trip whose times after midnight are written as early morning times, - # including the departure from its second stop - - overnight_gtfs <- gtfsio::new_gtfs( - list( - stop_times = data.table::data.table( - trip_id = "t1", - stop_id = c("s1", "s2", "s3"), - stop_sequence = 1:3, - arrival_time = c("23:50:00", "23:58:00", "00:05:00"), - departure_time = c("23:50:00", "00:01:00", "00:05:00") - ) - ), - "dt_gtfs" - ) +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + # a trip whose times after midnight are written as early morning times, + # including the departure from its second stop + + overnight_gtfs <- gtfsio::new_gtfs( + x = list( + stop_times = data.table::data.table( + trip_id = "t1", + stop_id = c("s1", "s2", "s3"), + stop_sequence = 1:3, + arrival_time = c("23:50:00", "23:58:00", "00:05:00"), + departure_time = c("23:50:00", "00:01:00", "00:05:00") + ) + ), + subclass = "dt_gtfs" + ) - original_gtfs <- gtfsio::new_gtfs( - lapply(overnight_gtfs, data.table::copy), - "dt_gtfs" - ) + original_gtfs <- gtfsio::new_gtfs( + x = lapply(X = overnight_gtfs, FUN = data.table::copy), + subclass = "dt_gtfs" + ) - expect_no_warning( - durations <- tester(overnight_gtfs), - class = "gtfstools_backwards_times" - ) - expect_equal(durations$duration, 15) - expect_equal(overnight_gtfs, original_gtfs, ignore_attr = TRUE) + expect_no_warning( + object = durations <- tester(gtfs = overnight_gtfs), + class = "gtfstools_backwards_times" + ) + expect_equal(object = durations$duration, expected = 15) + expect_equal( + object = overnight_gtfs, + expected = original_gtfs, + ignore_attr = TRUE + ) - poa_gtfs <- read_gtfs( - system.file("extdata/poa_gtfs.zip", package = "gtfstools") - ) - expect_equal(get_trip_duration(poa_gtfs, "T2-1@1#2310")$duration, 52) + poa_gtfs <- read_gtfs( + path = system.file("extdata/poa_gtfs.zip", package = "gtfstools") + ) + expect_equal( + object = get_trip_duration( + gtfs = poa_gtfs, + trip_id = "T2-1@1#2310" + )$duration, + expected = 52 + ) - # without stop_sequence the times can't be ordered, so they are used as - # written + # without stop_sequence the times can't be ordered, so they are used as + # written - no_sequence <- copy_gtfs_without_field( - overnight_gtfs, - "stop_times", - "stop_sequence" - ) - durations <- get_trip_duration(no_sequence) - expect_equal(durations$duration, 1437) -}) + no_sequence <- copy_gtfs_without_field( + gtfs = overnight_gtfs, + file = "stop_times", + field = "stop_sequence" + ) + durations <- get_trip_duration(gtfs = no_sequence) + expect_equal(object = durations$duration, expected = 1437) + } +) diff --git a/tests/testthat/test-get_trip_length.R b/tests/testthat/test-get_trip_length.R index 01649eff..6d85fc35 100644 --- a/tests/testthat/test-get_trip_length.R +++ b/tests/testthat/test-get_trip_length.R @@ -760,31 +760,34 @@ test_that("from and to select single-stop trips by their only stop", { expect_false("CPTM L07-0" %chin% result$trip_id) }) -test_that("selects segments after midnight from the fixed times", { - # W's segments from B (24:05) and C (24:20) depart after midnight - - gtfs <- overnight_feed() - lengths <- get_trip_length( - gtfs, - by = "segment", - method = "euclidean", - from = "24:00:00", - to = "25:00:00" - ) - durations <- get_trip_segment_duration( - gtfs, - from = "24:00:00", - to = "25:00:00" - ) - expect_identical(lengths$segment, c(2L, 3L)) - expect_identical(lengths$segment, durations$segment) - - lengths <- get_trip_length( - gtfs, - by = "segment", - method = "euclidean", - from = "00:00:00", - to = "01:00:00" - ) - expect_false("W" %chin% lengths$trip_id) -}) +test_that( + desc = "selects segments after midnight from the fixed times", + code = { + # W's segments from B (24:05) and C (24:20) depart after midnight + + gtfs <- overnight_feed() + lengths <- get_trip_length( + gtfs = gtfs, + by = "segment", + method = "euclidean", + from = "24:00:00", + to = "25:00:00" + ) + durations <- get_trip_segment_duration( + gtfs = gtfs, + from = "24:00:00", + to = "25:00:00" + ) + expect_identical(object = lengths$segment, expected = c(2L, 3L)) + expect_identical(object = lengths$segment, expected = durations$segment) + + lengths <- get_trip_length( + gtfs = gtfs, + by = "segment", + method = "euclidean", + from = "00:00:00", + to = "01:00:00" + ) + expect_false(object = "W" %chin% lengths$trip_id) + } +) diff --git a/tests/testthat/test-get_trip_segment_duration.R b/tests/testthat/test-get_trip_segment_duration.R index c7f404bc..259222e8 100644 --- a/tests/testthat/test-get_trip_segment_duration.R +++ b/tests/testthat/test-get_trip_segment_duration.R @@ -261,32 +261,39 @@ test_that("returns a typed empty table when stop_times is empty", { expect_type(tester(empty_gtfs)$duration, "double") }) -test_that("fixes times after midnight written as early morning times", { - # a trip whose times after midnight are written as early morning times, - # including the departure from its second stop - - overnight_gtfs <- gtfsio::new_gtfs( - list( - stop_times = data.table::data.table( - trip_id = "t1", - stop_id = c("s1", "s2", "s3"), - stop_sequence = 1:3, - arrival_time = c("23:50:00", "23:58:00", "00:05:00"), - departure_time = c("23:50:00", "00:01:00", "00:05:00") - ) - ), - "dt_gtfs" - ) - - original_gtfs <- gtfsio::new_gtfs( - lapply(overnight_gtfs, data.table::copy), - "dt_gtfs" - ) - - expect_no_warning( - durations <- tester(overnight_gtfs), - class = "gtfstools_backwards_times" - ) - expect_equal(durations$duration, c(8, 4)) - expect_equal(overnight_gtfs, original_gtfs, ignore_attr = TRUE) -}) +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + # a trip whose times after midnight are written as early morning times, + # including the departure from its second stop + + overnight_gtfs <- gtfsio::new_gtfs( + x = list( + stop_times = data.table::data.table( + trip_id = "t1", + stop_id = c("s1", "s2", "s3"), + stop_sequence = 1:3, + arrival_time = c("23:50:00", "23:58:00", "00:05:00"), + departure_time = c("23:50:00", "00:01:00", "00:05:00") + ) + ), + subclass = "dt_gtfs" + ) + + original_gtfs <- gtfsio::new_gtfs( + x = lapply(X = overnight_gtfs, FUN = data.table::copy), + subclass = "dt_gtfs" + ) + + expect_no_warning( + object = durations <- tester(gtfs = overnight_gtfs), + class = "gtfstools_backwards_times" + ) + expect_equal(object = durations$duration, expected = c(8, 4)) + expect_equal( + object = overnight_gtfs, + expected = original_gtfs, + ignore_attr = TRUE + ) + } +) diff --git a/tests/testthat/test-get_trip_speed.R b/tests/testthat/test-get_trip_speed.R index 4a1e5f14..65eae9f2 100644 --- a/tests/testthat/test-get_trip_speed.R +++ b/tests/testthat/test-get_trip_speed.R @@ -315,14 +315,20 @@ test_that("from and to raise the warnings only once", { } }) -test_that("fixes times after midnight written as early morning times", { - poa_gtfs <- read_gtfs( - system.file("extdata/poa_gtfs.zip", package = "gtfstools") - ) +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + poa_gtfs <- read_gtfs( + path = system.file("extdata/poa_gtfs.zip", package = "gtfstools") + ) - # this trip runs from 23:10:00 to "00:02:00" (i.e. 52 minutes) + # this trip runs from 23:10:00 to "00:02:00" (i.e. 52 minutes) - speed <- get_trip_speed(poa_gtfs, "T2-1@1#2310") - trip_length <- get_trip_length(poa_gtfs, "T2-1@1#2310") - expect_equal(speed$speed, trip_length$length / (52 / 60)) -}) + speed <- get_trip_speed(gtfs = poa_gtfs, trip_id = "T2-1@1#2310") + trip_length <- get_trip_length(gtfs = poa_gtfs, trip_id = "T2-1@1#2310") + expect_equal( + object = speed$speed, + expected = trip_length$length / (52 / 60) + ) + } +) diff --git a/tests/testthat/test-interpolate_stop_times.R b/tests/testthat/test-interpolate_stop_times.R index 694a8c13..08c1866b 100644 --- a/tests/testthat/test-interpolate_stop_times.R +++ b/tests/testthat/test-interpolate_stop_times.R @@ -136,13 +136,18 @@ test_that("handles times past midnight", { # times after midnight written as early morning times are fixed first - feed <- synthetic_feed(c(0, 0.01, 0.02), c("23:59:00", "", "00:01:00")) - original_stop_times <- data.table::copy(feed$stop_times) - expect_no_warning(result <- tester(feed, method = "euclidean")) - expect_identical(feed$stop_times, original_stop_times) + feed <- synthetic_feed( + stop_lon = c(0, 0.01, 0.02), + arrival_time = c("23:59:00", "", "00:01:00") + ) + original_stop_times <- data.table::copy(x = feed$stop_times) + expect_no_warning( + object = result <- tester(gtfs = feed, method = "euclidean") + ) + expect_identical(object = feed$stop_times, expected = original_stop_times) expect_identical( - result$stop_times$arrival_time, - c("23:59:00", "24:00:00", "24:01:00") + object = result$stop_times$arrival_time, + expected = c("23:59:00", "24:00:00", "24:01:00") ) }) @@ -261,7 +266,10 @@ test_that("falls back to euclidean distances without shapes", { }) test_that("leaves spans whose arrival is earlier than the departure blank", { - feed <- synthetic_feed(c(0, 0.01, 0.02), c("08:59:00", "", "08:57:00")) + feed <- synthetic_feed( + stop_lon = c(0, 0.01, 0.02), + arrival_time = c("08:59:00", "", "08:57:00") + ) expect_warning( result <- tester(feed, method = "euclidean"), regexp = "earlier than the previous departure", @@ -280,8 +288,8 @@ test_that("leaves spans whose arrival is earlier than the departure blank", { ) expect_match(conditionMessage(warning), "Affected trip") expect_match( - conditionMessage(warning), - "earlier than the previous departure" + object = conditionMessage(c = warning), + regexp = "earlier than the previous departure" ) }) @@ -616,11 +624,11 @@ test_that("fills poa's blank times, which never decrease", { # trips that cross midnight are written with times such as "00:02:00", # which are fixed first, so every blank time is filled expect_no_warning( - result <- tester(poa_gtfs), + object = result <- tester(gtfs = poa_gtfs), class = "gtfstools_times_not_interpolated" ) st <- data.table::copy(result$stop_times) - expect_false(any(st$arrival_time == "" | st$departure_time == "")) + expect_false(object = any(st$arrival_time == "" | st$departure_time == "")) st[, `:=`( arr = string_to_seconds(arrival_time), @@ -635,7 +643,7 @@ test_that("fills poa's blank times, which never decrease", { is_timepoint <- poa_gtfs$stop_times$arrival_time != "" expect_identical( result$stop_times$arrival_time[is_timepoint], - fix_overnight_times(poa_gtfs)$stop_times$arrival_time[is_timepoint] + fix_overnight_times(gtfs = poa_gtfs)$stop_times$arrival_time[is_timepoint] ) }) @@ -645,8 +653,8 @@ test_that("works with stop_times grouped by dplyr (#130)", { grouped_gtfs <- read_gtfs(poa_path) grouped_gtfs$stop_times <- dplyr::group_by(grouped_gtfs$stop_times, trip_id) - result <- tester(grouped_gtfs) + result <- tester(gtfs = grouped_gtfs) - expect_identical(result, tester()) + expect_identical(object = result, expected = tester()) expect_s3_class(grouped_gtfs$stop_times, "grouped_df") }) diff --git a/tests/testthat/test-set_dwell_time.R b/tests/testthat/test-set_dwell_time.R index d82e0b5e..fab8fa94 100644 --- a/tests/testthat/test-set_dwell_time.R +++ b/tests/testthat/test-set_dwell_time.R @@ -334,8 +334,8 @@ test_that("leaves visits with blank times unchanged with a warning", { class = "gtfstools_blank_dwell_time" ) expect_identical( - new_gtfs$stop_times, - fix_overnight_times(poa_gtfs)$stop_times + object = new_gtfs$stop_times, + expected = fix_overnight_times(gtfs = poa_gtfs)$stop_times ) # the warning counts the calls and the trips separately @@ -625,55 +625,70 @@ test_that("route_type restricts the changed visits", { expect_error(set_dwell_time(gtfs, dwell_time = 30, route_type = "2")) }) -test_that("fixes times after midnight written as early morning times", { - # a trip whose times after midnight are written as early morning times, - # including the departure from its second stop - - overnight_gtfs <- gtfsio::new_gtfs( - list( - stop_times = data.table::data.table( - trip_id = "t1", - stop_id = c("s1", "s2", "s3"), - stop_sequence = 1:3, - arrival_time = c("23:50:00", "23:58:00", "00:05:00"), - departure_time = c("23:50:00", "00:01:00", "00:05:00") - ) - ), - "dt_gtfs" - ) +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + # a trip whose times after midnight are written as early morning times, + # including the departure from its second stop + + overnight_gtfs <- gtfsio::new_gtfs( + x = list( + stop_times = data.table::data.table( + trip_id = "t1", + stop_id = c("s1", "s2", "s3"), + stop_sequence = 1:3, + arrival_time = c("23:50:00", "23:58:00", "00:05:00"), + departure_time = c("23:50:00", "00:01:00", "00:05:00") + ) + ), + subclass = "dt_gtfs" + ) - # the dwell time at s2 is 3 minutes, from 23:58:00 to "00:01:00" + # the dwell time at s2 is 3 minutes, from 23:58:00 to "00:01:00" - result <- set_dwell_time(overnight_gtfs, 120, stop_id = "s2") - expect_identical( - result$stop_times$departure_time, - c("23:50:00", "24:00:00", "24:04:00") - ) - expect_identical( - result$stop_times$arrival_time, - c("23:50:00", "23:58:00", "24:04:00") - ) - - # the time of day of a visit after midnight is compared as fixed + result <- set_dwell_time( + gtfs = overnight_gtfs, + dwell_time = 120, + stop_id = "s2" + ) + expect_identical( + object = result$stop_times$departure_time, + expected = c("23:50:00", "24:00:00", "24:04:00") + ) + expect_identical( + object = result$stop_times$arrival_time, + expected = c("23:50:00", "23:58:00", "24:04:00") + ) - expect_identical( - set_dwell_time( - overnight_gtfs, - 120, - stop_id = "s2", - from = "00:00:00", - to = "01:00:00" - )$stop_times, - fix_overnight_times(overnight_gtfs)$stop_times - ) + # the time of day of a visit after midnight is compared as fixed + + expect_identical( + object = set_dwell_time( + gtfs = overnight_gtfs, + dwell_time = 120, + stop_id = "s2", + from = "00:00:00", + to = "01:00:00" + )$stop_times, + expected = fix_overnight_times(gtfs = overnight_gtfs)$stop_times + ) - # by reference, the given feed gets the fixed times and the new dwell time + # by reference, the given feed gets the fixed times and the new dwell time - expect_invisible( - set_dwell_time(overnight_gtfs, 120, stop_id = "s2", by_reference = TRUE) - ) - expect_identical(overnight_gtfs$stop_times, result$stop_times) -}) + expect_invisible( + call = set_dwell_time( + gtfs = overnight_gtfs, + dwell_time = 120, + stop_id = "s2", + by_reference = TRUE + ) + ) + expect_identical( + object = overnight_gtfs$stop_times, + expected = result$stop_times + ) + } +) test_that("keep_total_duration splits the change and keeps the trip duration", { diff --git a/tests/testthat/test-set_max_speed.R b/tests/testthat/test-set_max_speed.R index d5c10a1c..0779fd79 100644 --- a/tests/testthat/test-set_max_speed.R +++ b/tests/testthat/test-set_max_speed.R @@ -232,7 +232,7 @@ test_that("keeps dwell times and blank times in feeds with blank times", { # first, so they are capped too expect_no_warning( - result <- tester(poa_gtfs, max_speed = 20), + object = result <- tester(gtfs = poa_gtfs, max_speed = 20), class = "gtfstools_backwards_times" ) @@ -356,31 +356,44 @@ test_that("leaves spans that end before they start unchanged, with a warning", { ) }) -test_that("fixes times after midnight written as early morning times", { - # the same trip, with times after midnight written as "00:xx:xx". they are - # fixed first, so the second span doesn't go back and is capped too +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + # the same trip, with times after midnight written as "00:xx:xx". they are + # fixed first, so the second span doesn't go back and is capped too - times <- c("23:58:00", "23:59:00", "00:01:00", "00:30:00", "00:31:00") - feed <- synthetic_feed(list(list(arr = times, dep = times)), route_id = "r1") + times <- c("23:58:00", "23:59:00", "00:01:00", "00:30:00", "00:31:00") + feed <- synthetic_feed( + times = list(list(arr = times, dep = times)), + route_id = "r1" + ) - expect_no_warning(result <- tester(feed)) + expect_no_warning(object = result <- tester(gtfs = feed)) - fixed <- c("23:58:00", "23:59:00", "24:01:00", "24:30:00", "24:31:00") - fixed_feed <- synthetic_feed( - list(list(arr = fixed, dep = fixed)), - route_id = "r1" - ) - expect_identical(result, tester(fixed_feed)) - expect_false(identical(result, fix_overnight_times(feed))) - - # a time of day with times after midnight written as "00:xx:xx" no longer - # matches the fixed stops + fixed <- c("23:58:00", "23:59:00", "24:01:00", "24:30:00", "24:31:00") + fixed_feed <- synthetic_feed( + times = list(list(arr = fixed, dep = fixed)), + route_id = "r1" + ) + expect_identical(object = result, expected = tester(gtfs = fixed_feed)) + expect_false( + object = identical(x = result, y = fix_overnight_times(gtfs = feed)) + ) - expect_identical( - tester(feed, first_stop = "s3", from = "00:00:00", to = "01:00:00"), - fix_overnight_times(feed) - ) -}) + # a time of day with times after midnight written as "00:xx:xx" no longer + # matches the fixed stops + + expect_identical( + object = tester( + gtfs = feed, + first_stop = "s3", + from = "00:00:00", + to = "01:00:00" + ), + expected = fix_overnight_times(gtfs = feed) + ) + } +) test_that("warns only about the selected trips with backwards spans", { backwards <- list( diff --git a/tests/testthat/test-set_min_dwell_time.R b/tests/testthat/test-set_min_dwell_time.R index da467857..95dad374 100644 --- a/tests/testthat/test-set_min_dwell_time.R +++ b/tests/testthat/test-set_min_dwell_time.R @@ -122,18 +122,25 @@ test_that("raises only shorter dwell times at intermediate stops", { # A's times are fixed, so only these change zero_min <- tester(min_dwell_time = 0) - expect_equal(zero_min, fix_overnight_times(dwell_gtfs), ignore_attr = TRUE) + expect_equal( + object = zero_min, + expected = fix_overnight_times(gtfs = dwell_gtfs), + ignore_attr = TRUE + ) # B departs from Y a minute before arriving there negative_gtfs <- dwell_feed() negative_gtfs$stop_times[7, departure_time := "09:04:00"] - zero_min <- tester(negative_gtfs, min_dwell_time = 0)$stop_times - expect_identical(zero_min$departure_time[7:8], c("09:05:00", "09:11:00")) - expect_identical(zero_min$arrival_time[8], "09:11:00") + zero_min <- tester(gtfs = negative_gtfs, min_dwell_time = 0)$stop_times + expect_identical( + object = zero_min$departure_time[7:8], + expected = c("09:05:00", "09:11:00") + ) + expect_identical(object = zero_min$arrival_time[8], expected = "09:11:00") expect_identical( - zero_min$departure_time[-(4:8)], - dwell_gtfs$stop_times$departure_time[-(4:8)] + object = zero_min$departure_time[-(4:8)], + expected = dwell_gtfs$stop_times$departure_time[-(4:8)] ) }) @@ -150,8 +157,8 @@ test_that("never shortens dwell times, whatever the trips and stops given", { expect_silent(first_stops <- tester(stop_id = "s0")) expect_equal( - first_stops, - fix_overnight_times(dwell_gtfs), + object = first_stops, + expected = fix_overnight_times(gtfs = dwell_gtfs), ignore_attr = TRUE ) diff --git a/tests/testthat/test-set_route_frequency.R b/tests/testthat/test-set_route_frequency.R index 7baa67ef..c20261cb 100644 --- a/tests/testthat/test-set_route_frequency.R +++ b/tests/testthat/test-set_route_frequency.R @@ -403,27 +403,33 @@ test_that("route_type restricts the changed routes", { ) }) -test_that("fixes times after midnight written as early morning times", { - # F departs every 30 minutes from 23:00 to "01:00:00". setting it to every - # 10 minutes from 23:30 to 24:30 replaces those departures, without - # doubling them - - gtfs <- overnight_feed() - result <- set_route_frequency( - gtfs, - "R2", - headway = 10, - from = "23:30:00", - to = "24:30:00" - ) - expect_identical(result$frequencies$end_time[3], "25:00:00") +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + # F departs every 30 minutes from 23:00 to "01:00:00". setting it to every + # 10 minutes from 23:30 to 24:30 replaces those departures, without + # doubling them + + gtfs <- overnight_feed() + result <- set_route_frequency( + gtfs = gtfs, + route_id = "R2", + headway = 10, + from = "23:30:00", + to = "24:30:00" + ) + expect_identical( + object = result$frequencies$end_time[3], + expected = "25:00:00" + ) - frequency <- get_route_frequency( - result, - "R2", - from = "23:30:00", - to = "24:30:00" - ) - expect_identical(frequency$departures, 6L) - expect_equal(frequency$mean_headway, 10) -}) + frequency <- get_route_frequency( + gtfs = result, + route_id = "R2", + from = "23:30:00", + to = "24:30:00" + ) + expect_identical(object = frequency$departures, expected = 6L) + expect_equal(object = frequency$mean_headway, expected = 10) + } +) diff --git a/tests/testthat/test-set_trip_speed.R b/tests/testthat/test-set_trip_speed.R index 8eae500b..903530e0 100644 --- a/tests/testthat/test-set_trip_speed.R +++ b/tests/testthat/test-set_trip_speed.R @@ -666,7 +666,7 @@ test_that("segment and time of day args work by reference and on other feeds", { # the other trips keep their times, except that times after midnight # written as early morning times are fixed - fixed_poa <- fix_overnight_times(poa_gtfs) + fixed_poa <- fix_overnight_times(gtfs = poa_gtfs) expect_identical( new_poa$stop_times[!trip_id %chin% in_window], fixed_poa$stop_times[!trip_id %chin% in_window] @@ -765,28 +765,53 @@ test_that("raises errors due to incorrect route_type and selection", { ) }) -test_that("fixes times after midnight written as early morning times", { - poa_gtfs <- read_gtfs( - system.file("extdata/poa_gtfs.zip", package = "gtfstools") - ) - trip <- "T2-1@1#2310" +test_that( + desc = "fixes times after midnight written as early morning times", + code = { + poa_gtfs <- read_gtfs( + path = system.file("extdata/poa_gtfs.zip", package = "gtfstools") + ) + trip <- "T2-1@1#2310" - # the returned feed has every trip's times after midnight fixed + # the returned feed has every trip's times after midnight fixed - expect_no_warning( - result <- set_trip_speed(poa_gtfs, trip, 20), - class = "gtfstools_backwards_times" - ) - expect_equal(get_trip_speed(result, trip)$speed, 20, tolerance = 1e-3) - others <- result$stop_times[trip_id != trip] - fixed_poa <- fix_overnight_times(poa_gtfs) - expect_identical(others, fixed_poa$stop_times[trip_id != trip]) + expect_no_warning( + object = result <- set_trip_speed( + gtfs = poa_gtfs, + trip_id = trip, + speed = 20 + ), + class = "gtfstools_backwards_times" + ) + expect_equal( + object = get_trip_speed(gtfs = result, trip_id = trip)$speed, + expected = 20, + tolerance = 1e-3 + ) + others <- result$stop_times[trip_id != trip] + fixed_poa <- fix_overnight_times(gtfs = poa_gtfs) + expect_identical( + object = others, + expected = fixed_poa$stop_times[trip_id != trip] + ) - # by reference, the given feed gets the fixed times and the new speed + # by reference, the given feed gets the fixed times and the new speed - given_gtfs <- read_gtfs( - system.file("extdata/poa_gtfs.zip", package = "gtfstools") - ) - expect_invisible(set_trip_speed(given_gtfs, trip, 20, by_reference = TRUE)) - expect_equal(given_gtfs$stop_times, result$stop_times, ignore_attr = TRUE) -}) + given_gtfs <- read_gtfs( + path = system.file("extdata/poa_gtfs.zip", package = "gtfstools") + ) + expect_invisible( + call = set_trip_speed( + gtfs = given_gtfs, + trip_id = trip, + speed = 20, + by_reference = TRUE + ) + ) + expect_equal( + object = given_gtfs$stop_times, + expected = result$stop_times, + ignore_attr = TRUE + ) + } +)