Skip to content

Commit

Permalink
Merge pull request #126 from selkamand/60-feat-request-assert_connection
Browse files Browse the repository at this point in the history
feat: added assert_connection
  • Loading branch information
selkamand authored Nov 13, 2024
2 parents 5865c07 + b1b52d1 commit 1666be6
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 10 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export(assert_character)
export(assert_character_vector)
export(assert_character_vector_or_glue)
export(assert_class)
export(assert_connection)
export(assert_create)
export(assert_create_chain)
export(assert_dataframe)
Expand Down
3 changes: 2 additions & 1 deletion R/assert.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#' Assert that conditions are met
#'
#' @param ... a list of conditions to check
#' @param msg A character string containing the error message to display if any of the conditions are not met. The string can include the placeholder {failed_expressions} to insert a list of the failed expressions. The string can also include {?s} and {?is/are} to insert the correct pluralization for the list of failed expressions.
#' @param msg A character string containing the error message to display if any of the conditions are not met.
#' The string can include the placeholder \{failed_expressions\} to insert a list of the failed expressions. The string can also include \{?s\} and \{?is/are\} to insert the correct pluralization for the list of failed expressions.
#' @inheritParams common_roxygen_params
#'
#' @return invisible(TRUE) if all conditions are met, otherwise aborts with the error message specified by msg
Expand Down
14 changes: 10 additions & 4 deletions R/assert_set.R
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,18 @@ assert_one_of <- assert_create_chain(
#'
#' @return Returns `invisible(TRUE)` if `x` and `y` contain all the same elements (ignoring order and duplicates), otherwise throws an error.
#' @examples
#' assert_set_equal(c(1, 2, 3), c(3, 2, 1)) # Passes because elements are the same, order doesn't matter
#' assert_set_equal(c("A", "B", "C"), c("C", "A", "B")) # Passes because elements are identical
#' # Passes because elements are the same, order doesn't matter
#' assert_set_equal(c(1, 2, 3), c(3, 2, 1))
#'
#' # Passes because elements are identical
#' assert_set_equal(c("A", "B", "C"), c("C", "A", "B"))
#'
#' try({
#' assert_set_equal(c(1, 2, 3), c(1, 2)) # Throws error because elements are not identical
#' assert_set_equal(c("A", "B"), c("A", "B", "C")) # Throws error because elements differ
#' # Throws error because elements are not identical
#' assert_set_equal(c(1, 2, 3), c(1, 2))
#'
#' # Throws error because elements differ
#' assert_set_equal(c("A", "B"), c("A", "B", "C"))
#' })
#' @export
assert_set_equal <- assert_create(
Expand Down
33 changes: 33 additions & 0 deletions R/assert_type.R
Original file line number Diff line number Diff line change
Expand Up @@ -565,3 +565,36 @@ assert_scalar <- assert_create(
default_error_msg = msg_helper_assert_type("scalar")
)

# Connections -----------------------------------------------------------------

#' Assert input is a database connection
#'
#' Assert the input object is a database connection, specifically of the "DBIConnection" class,
#' which is the standard virtual class used by the DBI package for database connections.
#' Note this assertion does not test if the database connection is valid and/or active.
#'
#' @param x An object to assert is a database connection
#' @param msg A custom error message displayed if `x` is not a valid database connection.
#' @inheritParams common_roxygen_params
#'
#' @return `invisible(TRUE)` if `x` is a valid database connection, otherwise aborts with an error message.
#'
#' @examples
#' try({
#' # Assuming a valid DBI connection `conn`:
#' assert_connection(conn) # Passes if `conn` is a DBI connection
#'
#' assert_connection(42) # Fails with error message
#' })
#'
#' @details
#' This function is designed for use with objects inheriting from the "DBIConnection" class, which is used widely across database connection implementations in R.
#' As other database interface packages are introduced, additional checks may be added to support other connection classes.
#'
#' @concept assert_type
#' @export
assert_connection <- assert_create(
func = is_connection,
default_error_msg = msg_helper_assert_type("database connection")
)

5 changes: 5 additions & 0 deletions R/is_functions.R
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ is_reactive <- function(x){
is_whole_number <- function(x){
return(x%%1==0)
}

is_connection <- function(x){
inherits(x, "DBIConnection")
}

# Advanced ----------------------------------------------------------------
# assert_create_advanced functions -----------------------------------------
# These functions are for feeding into assert_create_advanced
Expand Down
3 changes: 2 additions & 1 deletion man/assert.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions man/assert_connection.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions man/assert_set_equal.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions tests/testthat/test-assert_type.R
Original file line number Diff line number Diff line change
Expand Up @@ -523,3 +523,31 @@ cli::test_that_cli("assert_scalar() works", configs = "plain", {
# Custom error messages work
expect_error(assert_scalar(c(1, 2), msg = "Custom error message"), "Custom error message")
})


# Assert Connection ---------------------------------------------------------
cli::test_that_cli("assert_connection() works", configs = "plain", {

# Works for valid database connection objects
# conn <- DBI::dbConnect(RSQLite::SQLite(), ":memory:") # We use a mock connection instead since a real one would require more dependencies
conn <- structure(list(), class = c("SQLiteConnection", "DBIConnection"))

expect_true(assert_connection(conn))

# Aborts for non-connection objects
expect_error(assert_connection(42), "'42' must be a database connection, not a numeric", fixed = TRUE)
expect_error(assert_connection('not_a_connection'), "'\"not_a_connection\"' must be a database connection, not a character", fixed = TRUE)
expect_error(assert_connection(list()), "'list()' must be a database connection, not a list", fixed = TRUE)
expect_error(assert_connection(data.frame(a = 1)), "'data.frame(a = 1)' must be a database connection, not a data.frame", fixed = TRUE)


# Error messages use variable name of passed arguments
x <- list()
expect_error(assert_connection(x), "'x' must be a database connection, not a list", fixed = TRUE)

# Custom error messages work
expect_error(assert_connection(42, msg = "Custom error message"), "Custom error message")
})



0 comments on commit 1666be6

Please sign in to comment.