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 and contributing guide.
Developing {dittodb} requires is a bit more complication than developing other R packages for a few reasons:
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.
We currently test against the following database backends with GitHub Actions for CI:
All of these (with the exception of SQLite) are tested in the test
file test-dbi-generic-integration.R
. However, tests for
each database are only run if specific environment variables are set
that trigger them. The reason for this is so that it is easy to test
locally without needing to setup databases, but we are covered by these
tests being run on GitHub Actions. If you would like to run these tests
locally, you can set the following environment variables and run tests
as usual (e.g. with R CMD check
,
devtools::check()
, devtools::test()
)
DITTODB_ENABLE_PG_TESTS
is TRUE
, then
Postgres-based tests will be runDITTODB_ENABLE_MARIA_TESTS
is TRUE
,
then MariaDB-based tests will be runThere are a few scripts included in the db-setup
folder
that are helpful for setting up databases. For local tests, we highly
recommend using the docker scripts:
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.
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.
db-setup/[mariadb|postgres]-reset.sql
creates the
database nycflights
and test users (dropping them if they
already exist so they are fresh).db-setup/[mariadb|postgres]-nycflights.sql
creates the
necessary tables in the nycflights
database for use in
testing.db-setup/populate-dbs.sh
uses the above scripts to
populate the databases on GitHub Actions.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.
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.
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.
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.