From f3080855c666fc0b4f0867320bc1eff859dd1f75 Mon Sep 17 00:00:00 2001 From: Jonathan Keane Date: Mon, 8 Apr 2024 22:56:41 -0400 Subject: [PATCH] A bit of cleanup (#190) --- CONTRIBUTING.md | 8 +++--- DESCRIPTION | 2 +- NEWS.md | 4 +-- R/capture-requests.R | 3 ++- R/connection.R | 2 +- R/mock-db.R | 4 +-- R/mock-paths.R | 2 +- R/nycflights13-sql.R | 4 +-- R/redact.R | 2 +- R/use-dittodb.R | 10 ++++---- R/utils.R | 10 ++++---- README.md | 18 +++++++------- cran-comments.md | 2 +- man/check_db_path.Rd | 3 ++- man/mock-db-methods.Rd | 2 +- man/mockdb.Rd | 4 +-- man/nycflights_sqlite.Rd | 4 +-- man/redact_columns.Rd | 2 +- man/sanitize_table_id.Rd | 2 +- man/set_dittodb_debug_level.Rd | 8 +++--- man/use_dittodb.Rd | 10 ++++---- man/with_mock_path.Rd | 2 +- presentations/rstudio_conf_2021.md | 4 +-- revdep/README.md | 40 +++++++++++++++--------------- vignettes/developing-dittodb.Rmd | 22 ++++++++-------- vignettes/dittodb.Rmd | 14 +++++------ vignettes/nycflights.Rmd | 8 +++--- 27 files changed, 99 insertions(+), 97 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e3e49122..1a969a44 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ -# Contributing to {dittodb} +# Contributing to `dittodb` -This outlines how to propose a change to {dittodb}. For detailed information -about developing {dittodb} see the [developing {dittodb} vignette](articles/developing-dittodb.html). +This outlines how to propose a change to `dittodb`. For detailed information +about developing `dittodb` see the [developing `dittodb` vignette](articles/developing-dittodb.html). ### Fixing typos @@ -36,5 +36,5 @@ your PR. ### Code of Conduct -Please note that the {dittodb} project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). +Please note that the `dittodb` project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By contributing to this project, you agree to abide by its terms. diff --git a/DESCRIPTION b/DESCRIPTION index 4a89f370..4952fa09 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: dittodb Title: A Test Environment for Database Requests -Version: 0.1.7.9000 +Version: 0.1.8 Authors@R: c( person(given = "Jonathan", family = "Keane", diff --git a/NEWS.md b/NEWS.md index 3be30905..3648c615 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,5 @@ -# dittodb (development version) -* Improved error messages for connections made before running `start_db_capture()`. (#183) +# dittodb 0.1.8 +* Improved error messages for connections made before running `start_db_capture()`. (@KoderKow, #183) * Added to the `dbplyr` unique table names that are ignored to work with the newest `dbplyr` table names. (#188) # dittodb 0.1.7 diff --git a/R/capture-requests.R b/R/capture-requests.R index deb8701e..970074eb 100644 --- a/R/capture-requests.R +++ b/R/capture-requests.R @@ -435,7 +435,7 @@ get_redactor <- function() { return(NULL) } -#' Check dittodb environment path +#' Check for dittodb environment path #' #' This function should generally not be used, but must be exported for the #' query recording function to work properly @@ -443,6 +443,7 @@ get_redactor <- function() { #' @param .dittodb_env Environment object #' #' @return `NULL`, invisibly. +#' @keywords internal #' @export check_db_path <- function(.dittodb_env) { if (is.null(.dittodb_env$db_path)) { diff --git a/R/connection.R b/R/connection.R index 1c2f9a6c..9f60a86e 100644 --- a/R/connection.R +++ b/R/connection.R @@ -4,7 +4,7 @@ #' [DBI](https://CRAN.R-project.org/package=DBI) methods of the same name. #' Instead of actually interacting with a database, they read in mock responses #' and the code proceeds after that. These aren't used directly, but are part of -#' how {dittodb} works. +#' how `dittodb` works. #' #' @param conn a database connection (for dispatch with these methods, it should #' be of class `DBIMockConnection`) diff --git a/R/mock-db.R b/R/mock-db.R index f5db8967..95eb281d 100644 --- a/R/mock-db.R +++ b/R/mock-db.R @@ -4,7 +4,7 @@ #' use fixtures instead of connecting to a real database. Alternatively, you can #' start and stop using a mocked database with `start_mock_db()` and #' `stop_mock_db()` respectively.to execute the whole thing without needing to -#' remember to stop the mocking. When testing with {dittodb}, it will look for +#' remember to stop the mocking. When testing with `dittodb`, it will look for #' fixtures in all entries of [`db_mock_paths`]. #' #' You only need to use one approach: either use `start_mock_db()` to start @@ -17,7 +17,7 @@ #' #' Connections should be made after `start_mock_db()` if you're using that #' function or they should be made inside of `with_mock_db()` if you're using -#' that function because {dittodb} uses the database name (given in `dbname` or +#' that function because `dittodb` uses the database name (given in `dbname` or #' `Database` argument of [`dbConnect`] depending on the driver) to separate #' different fixtures. For ODBC connections with only a dsn provided, the dsn is #' used for this directory. diff --git a/R/mock-paths.R b/R/mock-paths.R index 3a6988f3..d16535ec 100644 --- a/R/mock-paths.R +++ b/R/mock-paths.R @@ -111,7 +111,7 @@ set_default_db_mock_paths <- function() { #' Run the DBI queries in an alternate mock directory #' #' When testing with dittodb, wrap your tests in `with_mock_path({})` to use the -#' database fixtures located in other directories. {dittodb} will look for +#' database fixtures located in other directories. `dittodb` will look for #' fixtures in the directory specified by the user, which can be a temporary #' or permanent location. #' diff --git a/R/nycflights13-sql.R b/R/nycflights13-sql.R index 22e5fa59..5a3a2bca 100644 --- a/R/nycflights13-sql.R +++ b/R/nycflights13-sql.R @@ -154,11 +154,11 @@ nycflights13_create_sqlite <- function(location = ":memory:", ...) { #' An SQLite connection to a subset of nycflights13 #' -#' Included with {dittodb} is a small subset of +#' Included with `dittodb` is a small subset of #' [`nycflights13`](https://CRAN.R-project.org/package=nycflights13) #' prepopulated into a `sqlite` database. #' -#' This database is helpful for getting to know {dittodb} and running example +#' This database is helpful for getting to know `dittodb` and running example #' code. It contains a small subset of the data in nycflights13: namely only the #' flights and planes that had a destination of ORD or MDW (the codes for the #' two major airports in Chicago) in February of 2013. The airports table has diff --git a/R/redact.R b/R/redact.R index d28dfe48..df629a95 100644 --- a/R/redact.R +++ b/R/redact.R @@ -1,7 +1,7 @@ #' Redact columns from a dataframe with the default redactors #' #' This function redacts the columns specified in `columns` in the data given in -#' `data` using {dittodb}'s standard redactors. +#' `data` using `dittodb`'s standard redactors. #' #' The column names given in the `columns` argument are treated as regular #' expressions, however they always have `^` and `$` added to the beginning and diff --git a/R/use-dittodb.R b/R/use-dittodb.R index bedd2eeb..1a74a8d1 100644 --- a/R/use-dittodb.R +++ b/R/use-dittodb.R @@ -1,18 +1,18 @@ -#' Use {dittodb} in your tests +#' Use `dittodb` in your tests #' -#' If you would like to use {dittodb} in your package, and you are already using +#' If you would like to use `dittodb` in your package, and you are already using #' [{testthat}](https://CRAN.R-project.org/package=testthat), use this function to -#' add {dittodb} to Suggests in the package DESCRIPTION and loads it in +#' add `dittodb` to Suggests in the package DESCRIPTION and loads it in #' `tests/testthat/helper.R`. Call it once when you're setting up a new package #' test suite. #' #' This function should be called with the path to your package source as the -#' `path` argument. The function is idempotent: if {dittodb} is already added to +#' `path` argument. The function is idempotent: if `dittodb` is already added to #' these files, no additional changes will be made. #' #' It will: #' -#' * add {dittodb} to the `Suggests` field of the DESCRIPTION file in the +#' * add `dittodb` to the `Suggests` field of the DESCRIPTION file in the #' current working directory #' * add `library(dittodb)` to the file `tests/testthat/helper.R` (creating it #' if it doesn't already exist) diff --git a/R/utils.R b/R/utils.R index 41085e8c..6d9f0429 100644 --- a/R/utils.R +++ b/R/utils.R @@ -134,18 +134,18 @@ ignore_quotes <- function(statement) { return(statement) } -#' Set {dittodb}'s debug level +#' Set `dittodb`'s debug level #' -#' It can be helpful to see what's going on by increasing {dittodb}'s verbosity +#' It can be helpful to see what's going on by increasing `dittodb`'s verbosity #' which will show what's going on under the hood (e.g. what queries are being #' requested, from where). This sets the option `dittodb.debug` to the value #' given in the `level` argument. The option can be set directly with #' `options(dittodb.debug = n)` as well. #' #' The `level` argument is a numeric, where 0 is the default and (relatively) -#' silent. The higher the level, the more verbose {dittodb} will be. +#' silent. The higher the level, the more verbose `dittodb` will be. #' -#' Currently, {dittodb} only has one level of debugging (any value 1 or +#' Currently, `dittodb` only has one level of debugging (any value 1 or #' greater), but more might be used in the future. #' #' @param level a numeric, the level to set to (e.g. 1) @@ -194,7 +194,7 @@ get_type <- function(statement) { #' Sanitize Table id #' #' Tables are identified and specified with a large number of ways across -#' drivers. For the purposes of {dittodb}, the details are less important since +#' drivers. For the purposes of `dittodb`, the details are less important since #' we almost always just want a flat representation (_ie_ for filenames). This #' takes the various formats and returns a string with various elements #' separated by dots. diff --git a/README.md b/README.md index 182994d8..62bfb342 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ [![Lifecycle: stable](https://lifecycle.r-lib.org/articles/figures/lifecycle-stable.svg)](https://lifecycle.r-lib.org/articles/stages.html) -{dittodb} is a package that makes testing against databases easy. When writing code that relies on interactions with databases, testing has been difficult without recreating test databases in your continuous integration (aka CI) environment, or resorting to using SQLite databases instead of the database engines you have in production. Both have their downsides: recreating database infrastructure is slow, error prone, and hard to iterate with. Using SQLite works well, right up until you use a feature (like [a full outer join](https://www.sqlite.org/omitted.html)) or has [quirks](https://www.sqlite.org/quirks.html) that might differ from your production database. {dittodb} solves this by recording database interactions, saving them as mocks, and then replaying them seamlessly during testing. This means that if you can get a query from your database, you can record the response and reliably reproduce that response in tests. +`dittodb` is a package that makes testing against databases easy. When writing code that relies on interactions with databases, testing has been difficult without recreating test databases in your continuous integration (aka CI) environment, or resorting to using SQLite databases instead of the database engines you have in production. Both have their downsides: recreating database infrastructure is slow, error prone, and hard to iterate with. Using SQLite works well, right up until you use a feature (like [a full outer join](https://www.sqlite.org/omitted.html)) or has [quirks](https://www.sqlite.org/quirks.html) that might differ from your production database. `dittodb` solves this by recording database interactions, saving them as mocks, and then replaying them seamlessly during testing. This means that if you can get a query from your database, you can record the response and reliably reproduce that response in tests. -{dittodb} is heavily inspired by [{httptest}](https://CRAN.R-project.org/package=httptest), if you've used {httptest} before, you'll find many of the interactions similar. +`dittodb` is heavily inspired by [{httptest}](https://CRAN.R-project.org/package=httptest), if you've used {httptest} before, you'll find many of the interactions similar. ## A quick example Say we have a database with some [{nycflights}](https://CRAN.R-project.org/package=nycflights13) data in it and we are writing functions that query this data that we want to test. @@ -130,7 +130,7 @@ with_mock_db({ All without having to ever set a database up on Travis or GitHub Actions 🎉 ## Installation -Currently, {dittodb} is on CRAN (The Comprehensive R Archive Network), so you can install it with `install.packages("dittodb")`. +Currently, `dittodb` is on CRAN (The Comprehensive R Archive Network), so you can install it with `install.packages("dittodb")`. ### Installing a development version @@ -138,18 +138,18 @@ If you would like to use the development version, you can install from GitHub wi _Note_ You may need to add `@main` at the end if you are using a version of {remotes} prior to 2.2.0. Alternatively, you can use `remotes::install_git()` directly: `remotes::install_git("https://github.com/ropensci/dittodb.git")` -## Setup a package to use {dittodb} -Use the function `dittodb::use_dittodb()` to easily get started using {dittodb}. It will add {dittodb} to `Suggests` in the `DESCRIPTION` file and add `library(dittodb)` to `tests/testthat/helper.R`. +## Setup a package to use `dittodb` +Use the function `dittodb::use_dittodb()` to easily get started using `dittodb`. It will add `dittodb` to `Suggests` in the `DESCRIPTION` file and add `library(dittodb)` to `tests/testthat/helper.R`. ## Development -There is extensive information about developing {dittodb} in the vignette [Developing {dittodb}](https://dittodb.jonkeane.com/articles/developing-dittodb.html), please read that before trying to make changes to {dittodb} or running any of the scripts provided in the `db-setup` directory. +There is extensive information about developing `dittodb` in the vignette [Developing `dittodb`](https://dittodb.jonkeane.com/articles/developing-dittodb.html), please read that before trying to make changes to `dittodb` or running any of the scripts provided in the `db-setup` directory. -In order to test {dittodb} recording functionality locally or on continuous integration, it is helpful to have databases with test data available. This can be accomplished using the scripts in the `db-setup` directory. By default, {dittodb} does not run any tests that require database infrastructure locally. +In order to test `dittodb` recording functionality locally or on continuous integration, it is helpful to have databases with test data available. This can be accomplished using the scripts in the `db-setup` directory. By default, `dittodb` does not run any tests that require database infrastructure locally. -To get local databases, the easiest way is to use docker and run either the `db-setup/local-mariadb-docker-setup.sh` or `db-setup/local-postgres-docker-setup.sh` which will pull a docker image and set up a test database with the user and passwords that the {dittodb} tests are expecting (and will stop and remove the docker images if they are present). +To get local databases, the easiest way is to use docker and run either the `db-setup/local-mariadb-docker-setup.sh` or `db-setup/local-postgres-docker-setup.sh` which will pull a docker image and set up a test database with the user and passwords that the `dittodb` tests are expecting (and will stop and remove the docker images if they are present). On continuous integration, (using GitHub Actions) these scripts in the `db-setup` directory are used to set up these test databases so we can run integration tests (predominantly in the file `tests/testthat/test-dbi-generic-integration.R`). ## Code of Conduct -Please note that the {dittodb} project is released with a [Contributor Code of Conduct](https://dittodb.jonkeane.com/CODE_OF_CONDUCT). By contributing to this project, you agree to abide by its terms. +Please note that the `dittodb` project is released with a [Contributor Code of Conduct](https://dittodb.jonkeane.com/CODE_OF_CONDUCT). By contributing to this project, you agree to abide by its terms. diff --git a/cran-comments.md b/cran-comments.md index 920c4db1..9ff98625 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,5 +1,5 @@ ## Test environments -* local R installation MacOS 12.6.8, R 4.3.0 +* local R installation MacOS 14.4.1, R 4.3.3 * ubuntu 22.04 (on GitHub actions), R 3.6-4.3, devel * macOS (on GitHub actions), R 4.2, 4.3 * windows (on GitHub actions), R 4.3 diff --git a/man/check_db_path.Rd b/man/check_db_path.Rd index c7433e29..05698a18 100644 --- a/man/check_db_path.Rd +++ b/man/check_db_path.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/capture-requests.R \name{check_db_path} \alias{check_db_path} -\title{Check dittodb environment path} +\title{Check for dittodb environment path} \usage{ check_db_path(.dittodb_env) } @@ -16,3 +16,4 @@ check_db_path(.dittodb_env) This function should generally not be used, but must be exported for the query recording function to work properly } +\keyword{internal} diff --git a/man/mock-db-methods.Rd b/man/mock-db-methods.Rd index cd230a25..a0ad2175 100644 --- a/man/mock-db-methods.Rd +++ b/man/mock-db-methods.Rd @@ -136,5 +136,5 @@ Various methods (\code{dbSendQuery}, \code{dbFetchQuery}) that are mocks of the \href{https://CRAN.R-project.org/package=DBI}{DBI} methods of the same name. Instead of actually interacting with a database, they read in mock responses and the code proceeds after that. These aren't used directly, but are part of -how {dittodb} works. +how \code{dittodb} works. } diff --git a/man/mockdb.Rd b/man/mockdb.Rd index 7572b177..452d35a1 100644 --- a/man/mockdb.Rd +++ b/man/mockdb.Rd @@ -24,7 +24,7 @@ Wrap a chunk of code in \code{with_mock_db()} to use mocked databases that will use fixtures instead of connecting to a real database. Alternatively, you can start and stop using a mocked database with \code{start_mock_db()} and \code{stop_mock_db()} respectively.to execute the whole thing without needing to -remember to stop the mocking. When testing with {dittodb}, it will look for +remember to stop the mocking. When testing with \code{dittodb}, it will look for fixtures in all entries of \code{\link{db_mock_paths}}. } \details{ @@ -38,7 +38,7 @@ step through tests interactively using \code{start_mock_db()}/\code{stop_mock_db Connections should be made after \code{start_mock_db()} if you're using that function or they should be made inside of \code{with_mock_db()} if you're using -that function because {dittodb} uses the database name (given in \code{dbname} or +that function because \code{dittodb} uses the database name (given in \code{dbname} or \code{Database} argument of \code{\link{dbConnect}} depending on the driver) to separate different fixtures. For ODBC connections with only a dsn provided, the dsn is used for this directory. diff --git a/man/nycflights_sqlite.Rd b/man/nycflights_sqlite.Rd index 8ca433e8..803729ca 100644 --- a/man/nycflights_sqlite.Rd +++ b/man/nycflights_sqlite.Rd @@ -10,12 +10,12 @@ nycflights_sqlite() an RSQLiteConnection } \description{ -Included with {dittodb} is a small subset of +Included with \code{dittodb} is a small subset of \href{https://CRAN.R-project.org/package=nycflights13}{\code{nycflights13}} prepopulated into a \code{sqlite} database. } \details{ -This database is helpful for getting to know {dittodb} and running example +This database is helpful for getting to know \code{dittodb} and running example code. It contains a small subset of the data in nycflights13: namely only the flights and planes that had a destination of ORD or MDW (the codes for the two major airports in Chicago) in February of 2013. The airports table has diff --git a/man/redact_columns.Rd b/man/redact_columns.Rd index 1acff4be..c2561d83 100644 --- a/man/redact_columns.Rd +++ b/man/redact_columns.Rd @@ -21,7 +21,7 @@ data, with the columns specified in \code{columns} duly redacted } \description{ This function redacts the columns specified in \code{columns} in the data given in -\code{data} using {dittodb}'s standard redactors. +\code{data} using \code{dittodb}'s standard redactors. } \details{ The column names given in the \code{columns} argument are treated as regular diff --git a/man/sanitize_table_id.Rd b/man/sanitize_table_id.Rd index ceb78aa2..05f840c7 100644 --- a/man/sanitize_table_id.Rd +++ b/man/sanitize_table_id.Rd @@ -17,7 +17,7 @@ the first word in the statement } \description{ Tables are identified and specified with a large number of ways across -drivers. For the purposes of {dittodb}, the details are less important since +drivers. For the purposes of \code{dittodb}, the details are less important since we almost always just want a flat representation (\emph{ie} for filenames). This takes the various formats and returns a string with various elements separated by dots. diff --git a/man/set_dittodb_debug_level.Rd b/man/set_dittodb_debug_level.Rd index 808dbeac..2f740528 100644 --- a/man/set_dittodb_debug_level.Rd +++ b/man/set_dittodb_debug_level.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/utils.R \name{set_dittodb_debug_level} \alias{set_dittodb_debug_level} -\title{Set {dittodb}'s debug level} +\title{Set \code{dittodb}'s debug level} \usage{ set_dittodb_debug_level(level) } @@ -13,7 +13,7 @@ set_dittodb_debug_level(level) the level, invisibly } \description{ -It can be helpful to see what's going on by increasing {dittodb}'s verbosity +It can be helpful to see what's going on by increasing \code{dittodb}'s verbosity which will show what's going on under the hood (e.g. what queries are being requested, from where). This sets the option \code{dittodb.debug} to the value given in the \code{level} argument. The option can be set directly with @@ -21,9 +21,9 @@ given in the \code{level} argument. The option can be set directly with } \details{ The \code{level} argument is a numeric, where 0 is the default and (relatively) -silent. The higher the level, the more verbose {dittodb} will be. +silent. The higher the level, the more verbose \code{dittodb} will be. -Currently, {dittodb} only has one level of debugging (any value 1 or +Currently, \code{dittodb} only has one level of debugging (any value 1 or greater), but more might be used in the future. } \examples{ diff --git a/man/use_dittodb.Rd b/man/use_dittodb.Rd index 88cc7e5d..d2527c38 100644 --- a/man/use_dittodb.Rd +++ b/man/use_dittodb.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/use-dittodb.R \name{use_dittodb} \alias{use_dittodb} -\title{Use {dittodb} in your tests} +\title{Use \code{dittodb} in your tests} \usage{ use_dittodb(path = ".") } @@ -13,20 +13,20 @@ use_dittodb(path = ".") Nothing: called for file system side effects. } \description{ -If you would like to use {dittodb} in your package, and you are already using +If you would like to use \code{dittodb} in your package, and you are already using \href{https://CRAN.R-project.org/package=testthat}{{testthat}}, use this function to -add {dittodb} to Suggests in the package DESCRIPTION and loads it in +add \code{dittodb} to Suggests in the package DESCRIPTION and loads it in \code{tests/testthat/helper.R}. Call it once when you're setting up a new package test suite. } \details{ This function should be called with the path to your package source as the -\code{path} argument. The function is idempotent: if {dittodb} is already added to +\code{path} argument. The function is idempotent: if \code{dittodb} is already added to these files, no additional changes will be made. It will: \itemize{ -\item add {dittodb} to the \code{Suggests} field of the DESCRIPTION file in the +\item add \code{dittodb} to the \code{Suggests} field of the DESCRIPTION file in the current working directory \item add \code{library(dittodb)} to the file \code{tests/testthat/helper.R} (creating it if it doesn't already exist) diff --git a/man/with_mock_path.Rd b/man/with_mock_path.Rd index 4900b304..d8efd561 100644 --- a/man/with_mock_path.Rd +++ b/man/with_mock_path.Rd @@ -20,7 +20,7 @@ nothing, called to execute the expression(s) in \code{expr} } \description{ When testing with dittodb, wrap your tests in \code{with_mock_path({})} to use the -database fixtures located in other directories. {dittodb} will look for +database fixtures located in other directories. \code{dittodb} will look for fixtures in the directory specified by the user, which can be a temporary or permanent location. } diff --git a/presentations/rstudio_conf_2021.md b/presentations/rstudio_conf_2021.md index eb14195e..cdc060e6 100644 --- a/presentations/rstudio_conf_2021.md +++ b/presentations/rstudio_conf_2021.md @@ -13,9 +13,9 @@ Hello I'm Jonathan Keane — while I was trained as a linguist — I have been w Early on in my career I fell down the rabbit hole of test driven development and have been using it ever since. Testing has not only saved me from costly mistakes or bugs I never would have caught without it, it has also made it easier to write better code. -This passion for testing led me to developing the package {dittodb}. {dittodb} makes testing database interactions fast, simple, and fun. It uses the DBI interface to make it easy to set up a mocked database driven by static fixtures so tests are quick and can run anywhere. Though there are packages that make testing HTTP-based APIs easy, like {httptest} and {webmockr}, until {dittodb} there wasn't an equivalent package that made testing database interactions simple. +This passion for testing led me to developing the package `dittodb`. `dittodb` makes testing database interactions fast, simple, and fun. It uses the DBI interface to make it easy to set up a mocked database driven by static fixtures so tests are quick and can run anywhere. Though there are packages that make testing HTTP-based APIs easy, like {httptest} and {webmockr}, until `dittodb` there wasn't an equivalent package that made testing database interactions simple. -Through my talk, people will have an understanding of how to test databse interactions using {dittodb} as well as some more general testing-related ideas about what makes a good test and how testing can improve your R code as well your life as a developer. +Through my talk, people will have an understanding of how to test databse interactions using `dittodb` as well as some more general testing-related ideas about what makes a good test and how testing can improve your R code as well your life as a developer. I love building and contributing to tools that help people interact with data and empower them to be able to analyze and model their data better, faster, and easier. diff --git a/revdep/README.md b/revdep/README.md index 8e84066c..528c2ddf 100644 --- a/revdep/README.md +++ b/revdep/README.md @@ -1,30 +1,30 @@ # Platform -|field |value | -|:--------|:------------------------------------------| -|version |R version 4.3.0 (2023-04-21) | -|os |macOS Monterey 12.6.8 | -|system |x86_64, darwin20 | -|ui |RStudio | -|language |(EN) | -|collate |en_US.UTF-8 | -|ctype |en_US.UTF-8 | -|tz |America/Chicago | -|date |2023-08-12 | -|rstudio |2023.06.1+524 Mountain Hydrangea (desktop) | -|pandoc |3.1.5 @ /usr/local/bin/pandoc | +|field |value | +|:--------|:------------------------------------------------------------------------------------------| +|version |R version 4.3.3 (2024-02-29) | +|os |macOS Sonoma 14.4.1 | +|system |aarch64, darwin20 | +|ui |RStudio | +|language |(EN) | +|collate |en_US.UTF-8 | +|ctype |en_US.UTF-8 | +|tz |America/New_York | +|date |2024-04-08 | +|rstudio |2023.12.1+402 Ocean Storm (desktop) | +|pandoc |3.1.1 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown) | # Dependencies |package |old |new |Δ | |:---------|:------|:----------|:--| -|dittodb |0.1.6 |0.1.6.9000 |* | -|cli |3.6.1 |3.6.1 | | -|DBI |1.1.3 |1.1.3 | | -|digest |0.6.33 |0.6.33 | | -|glue |1.6.2 |1.6.2 | | -|lifecycle |1.0.3 |1.0.3 | | -|rlang |1.1.1 |1.1.1 | | +|dittodb |0.1.7 |0.1.7.9000 |* | +|cli |NA |3.6.2 |* | +|DBI |NA |1.2.2 |* | +|digest |0.6.35 |0.6.35 | | +|glue |NA |1.7.0 |* | +|lifecycle |NA |1.0.4 |* | +|rlang |NA |1.1.3 |* | # Revdeps diff --git a/vignettes/developing-dittodb.Rmd b/vignettes/developing-dittodb.Rmd index b0e374a3..df5d7f60 100644 --- a/vignettes/developing-dittodb.Rmd +++ b/vignettes/developing-dittodb.Rmd @@ -1,10 +1,10 @@ --- -title: "Developing {dittodb}" +title: "Developing `dittodb`" author: "Jonathan Keane" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Developing {dittodb}} + %\VignetteIndexEntry{Developing `dittodb`} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -23,13 +23,13 @@ db_mock_paths("dittodb") We welcome contributions from anyone, no matter how small or trivial. Documentation additions or typo fixes are especially welcome. For larger, more-functional changes, either see if there is an issue open on GitHub already, or open one with a proposal of the change you would like to make. Please also see our [code of conduct](../docs/CODE_OF_CONDUCT.html) and [contributing guide](../docs/CONTRIBUTING.html). -Developing {dittodb} requires is a bit more complication than developing other R packages for a few reasons: +Developing `dittodb` requires is a bit more complication than developing other R packages for a few reasons: -1. setting up all of the databases to fully test recording is complicated (which is in some ways the exact reason {dittodb} exists, so you don't have to do this!) -2. some of the mechanisms that make {dittodb} work aren't commonly used in other R packages. +1. setting up all of the databases to fully test recording is complicated (which is in some ways the exact reason `dittodb` exists, so you don't have to do this!) +2. some of the mechanisms that make `dittodb` work aren't commonly used in other R packages. ## Setting up databases -In order to fully test that {dittodb} works, we aim to have full coverage and test as many database backends as possible for both recording and using as a mocked database. To do this on continuous integration (CI for short) can be finicky to get working (and on the CI front, we did it once, so that you can use {dittodb} and you won't have to setup your own database backend just to run tests!). Frankly, even doing this set up locally on a second computer can be a pain! We include in the repository a few scripts that make it (relatively) easy to setup testing database backends, as well as some scripts that we use to setup database backends on GitHub Actions. +In order to fully test that `dittodb` works, we aim to have full coverage and test as many database backends as possible for both recording and using as a mocked database. To do this on continuous integration (CI for short) can be finicky to get working (and on the CI front, we did it once, so that you can use `dittodb` and you won't have to setup your own database backend just to run tests!). Frankly, even doing this set up locally on a second computer can be a pain! We include in the repository a few scripts that make it (relatively) easy to setup testing database backends, as well as some scripts that we use to setup database backends on GitHub Actions. ### What we test We currently test against the following database backends with GitHub Actions for CI: @@ -49,7 +49,7 @@ There are a few scripts included in the `db-setup` folder that are helpful for s * `db-setup/local-mariadb-docker-setup.sh` which starts (or stops and then starts if it's already running) a docker container, installs MariaDB in that container (running on the default port 3306), and loads the correct test user and test data into the database for running tests. * `db-setup/local-postgres-docker-setup.sh` which starts (or stops and then starts if it's already running) a docker container, installs Postgres in that container (running on the default port 5432), and loads the correct test user and test data into the database for running tests. -If you've already got databases running on the default ports (3306 for MariaDB and 5432 for Postgres) and you want to use the docker scripts, we recommend that you change the ports that docker is using for any databases you're already running. You can use the `DITTODB_MARIA_TEST_PORT` and `DITTODB_PG_TEST_PORT` environment variables to change which port {dittodb} uses to connect to the test databases. The docker scripts above will use these environment variables to map ports if they are set (and exported) for convenience. One thing to note: during {dittodb} tests, if some database drivers attempt to connect to not-running or on-the-wrong-port database backends, they can segfault instead of erroring with a more informative error. If you see this, the first thing to check is that the port variables are being set correctly and that the database backend is up and running normally. +If you've already got databases running on the default ports (3306 for MariaDB and 5432 for Postgres) and you want to use the docker scripts, we recommend that you change the ports that docker is using for any databases you're already running. You can use the `DITTODB_MARIA_TEST_PORT` and `DITTODB_PG_TEST_PORT` environment variables to change which port `dittodb` uses to connect to the test databases. The docker scripts above will use these environment variables to map ports if they are set (and exported) for convenience. One thing to note: during `dittodb` tests, if some database drivers attempt to connect to not-running or on-the-wrong-port database backends, they can segfault instead of erroring with a more informative error. If you see this, the first thing to check is that the port variables are being set correctly and that the database backend is up and running normally. Both of these utilize a few SQL (Structured Query Language) scripts for their respective backends. These might be useful if you're manually adding the test data into a database you already have running, but if you're using the docker scripts above, you shouldn't need to use them at all. @@ -60,11 +60,11 @@ Both of these utilize a few SQL (Structured Query Language) scripts for their re ### ☠️ What not to run ☠️ The other scripts (e.g. `db-setup/[mariadb|postgres]-brew.sh` and `db-setup/[mariadb|postgres]-docker-container-only.sh`) are only intended for use on GitHub Actions and should not be run locally. They include commands that will remove files necessary to reset database setups that allow for tests to be run. Running them locally will delete files that you might care about. -## Some of the tricky bits that {dittodb} uses -In order to provide a seamless experience between using a real database connection and using the mocked version of the database {dittodb} uses some features of R that are pretty uncommon. This is not intended to be a comprehensive description of {dittodb}'s architecture, but a few things that are uncommon or a little strange. +## Some of the tricky bits that `dittodb` uses +In order to provide a seamless experience between using a real database connection and using the mocked version of the database `dittodb` uses some features of R that are pretty uncommon. This is not intended to be a comprehensive description of `dittodb`'s architecture, but a few things that are uncommon or a little strange. ### Recording -In order to record fixtures while using a real database connection, we use `base::trace()` to add code that inspects the queries (to define unique hashes) and saves the results so that they can be used later. This tracing only happens when using the `start_db_capturing()` functions and should generally not be used during testing by packages that use {dittodb}. Rather, this functionality should generally be used to see what interactions a piece of code to be tested is having with a database and either use or edit and use the fixtures it produces in testing. +In order to record fixtures while using a real database connection, we use `base::trace()` to add code that inspects the queries (to define unique hashes) and saves the results so that they can be used later. This tracing only happens when using the `start_db_capturing()` functions and should generally not be used during testing by packages that use `dittodb`. Rather, this functionality should generally be used to see what interactions a piece of code to be tested is having with a database and either use or edit and use the fixtures it produces in testing. ### Using a mocked database -When using fixtures (i.e. with a mocked database), we use some internals to mock the `DBI::dbConnect()` function and replace the true connection with a special mock connection class from {dittodb} (`DBIMockConnection`, though there are specific sub-classes for some drivers, e.g. `DBIMockRPostgresConnection`). Then {dittodb} relies on standard S4 method dispatch to find the appropriate fixture for queries being run during testing. +When using fixtures (i.e. with a mocked database), we use some internals to mock the `DBI::dbConnect()` function and replace the true connection with a special mock connection class from `dittodb` (`DBIMockConnection`, though there are specific sub-classes for some drivers, e.g. `DBIMockRPostgresConnection`). Then `dittodb` relies on standard S4 method dispatch to find the appropriate fixture for queries being run during testing. diff --git a/vignettes/dittodb.Rmd b/vignettes/dittodb.Rmd index 5cd0c992..4e1dc7bd 100644 --- a/vignettes/dittodb.Rmd +++ b/vignettes/dittodb.Rmd @@ -1,10 +1,10 @@ --- -title: "Getting Started with {dittodb}" +title: "Getting Started with `dittodb`" author: "Jonathan Keane" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Getting Started with {dittodb}} + %\VignetteIndexEntry{Getting Started with `dittodb`} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -21,7 +21,7 @@ knitr::opts_chunk$set( db_mock_paths("dittodb") ``` -{dittodb} is designed to make it easy and fun to test functions that interact with a database. It works by looking for mock responses for each query you send while you run your tests and will seamlessly pretend that those mocks were provided by the database connection without needing a connection at all. +`dittodb` is designed to make it easy and fun to test functions that interact with a database. It works by looking for mock responses for each query you send while you run your tests and will seamlessly pretend that those mocks were provided by the database connection without needing a connection at all. ```{r setup db, include = FALSE, eval = FALSE} # setup the DB used in the rest of the vignette @@ -194,9 +194,9 @@ with_mock_db( ) ``` -## Getting setup to use {dittodb} -Use the function `dittodb::use_dittodb()` to easily get started using {dittodb}. -It will add {dittodb} to `Suggests` in the `DESCRIPTION` file and add `library(dittodb)` +## Getting setup to use `dittodb` +Use the function `dittodb::use_dittodb()` to easily get started using `dittodb`. +It will add `dittodb` to `Suggests` in the `DESCRIPTION` file and add `library(dittodb)` to `tests/testthat/helper.R`. ## Things to be careful about @@ -226,7 +226,7 @@ You can add a new path by calling `db_mock_paths("new/path/here")` which will ad ### Redacting -Sometimes (much? most? of the time!) there is sensitive data in your database that you don't actually want to put into your test fixtures. {dittodb} allows you to specify columns that should always be redacted by specifying them like so: +Sometimes (much? most? of the time!) there is sensitive data in your database that you don't actually want to put into your test fixtures. `dittodb` allows you to specify columns that should always be redacted by specifying them like so: ``` start_db_capturing(redact_columns = c("sensitive_column", "other_sensitive_column")) ``` diff --git a/vignettes/nycflights.Rmd b/vignettes/nycflights.Rmd index 7716e19f..f05e9a5a 100644 --- a/vignettes/nycflights.Rmd +++ b/vignettes/nycflights.Rmd @@ -18,7 +18,7 @@ db_mock_paths("nycflights13") knitr::opts_chunk$set(eval = TRUE, message = FALSE, warning = FALSE) ``` -{dittodb} uses the [{nycflights13}](https://CRAN.R-project.org/package=nycflights13) dataset for testing and example purposes. +`dittodb` uses the [{nycflights13}](https://CRAN.R-project.org/package=nycflights13) dataset for testing and example purposes. # Exploring {nycflights13} The {nycflights13} dataset contains airline on-time data for all flights @@ -30,15 +30,15 @@ Have a look to the database schema: ![{nycflights13} relational diagram.](relational-nycflights.svg) # {nycflights13} test database -{dittodb} comes with a small subset of {nycflights13} to be used in testing and +`dittodb` comes with a small subset of {nycflights13} to be used in testing and examples. To access it, use the convenience function `nycflights_sqlite()` which will return an `RSQLite` connection the the `nycflights.sqlite` file included -with {dittodb}. Alternatively, you can connect to this file with +with `dittodb`. Alternatively, you can connect to this file with `system.file("nycflights.sqlite", package = "dittodb")`. # Adding {nycflights13} data to a database -{dittodb} has a few functions that make loading {nycflights13} data into a +`dittodb` has a few functions that make loading {nycflights13} data into a database easier. `nycflights13_create_sql(con, schema = "nycflights")` will write the {nycflights13} data to the database connect to with `con` and write it to the schema `nycflights`.