Skip to content

Commit

Permalink
version 0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Ian Cero authored and cran-robot committed Sep 12, 2023
0 parents commit 092af94
Show file tree
Hide file tree
Showing 50 changed files with 4,403 additions and 0 deletions.
31 changes: 31 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Package: checkthat
Title: Intuitive Unit Testing Tools for Data Manipulation
Version: 0.1.0
Authors@R:
person("Ian", "Cero", , "ian_cero@urmc.rochester.edu", role = c("aut",
"cre", "cph"), comment = c(ORCID = "0000-0002-2862-0450"))
Description: Provides a lightweight data validation and testing toolkit for R.
Its guiding philosophy is that adding code-based data checks to users'
existing workflow should be both quick and intuitive. The suite of
functions included therefore mirror the common data checks many users
already perform by hand or by eye. Additionally, the 'checkthat' package is
optimized to work within 'tidyverse' data manipulation pipelines.
License: MIT + file LICENSE
URL: https://github.com/iancero/checkthat,
https://iancero.github.io/checkthat/
BugReports: https://github.com/iancero/checkthat/issues
Depends: R (>= 4.3)
Imports: cli (>= 3.6.1), glue (>= 1.6.2), lifecycle (>= 1.0.3), purrr
(>= 1.0.2), rlang (>= 1.1.1)
Suggests: dplyr (>= 1.1.2), knitr (>= 1.43.0), lubridate (>= 1.9.2),
rmarkdown (>= 2.23.0), testthat (>= 3.0.0), tidyr (>= 1.3.0)
Config/testthat/edition: 3
Encoding: UTF-8
RoxygenNote: 7.2.3
VignetteBuilder: knitr
NeedsCompilation: no
Packaged: 2023-09-12 03:00:47 UTC; icero
Author: Ian Cero [aut, cre, cph] (<https://orcid.org/0000-0002-2862-0450>)
Maintainer: Ian Cero <ian_cero@urmc.rochester.edu>
Repository: CRAN
Date/Publication: 2023-09-12 20:30:05 UTC
2 changes: 2 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
YEAR: 2023
COPYRIGHT HOLDER: Ian Cero
49 changes: 49 additions & 0 deletions MD5
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
59f1e429fbf6ea279b665722d8aef315 *DESCRIPTION
185c190330274738dede4433304eda7a *LICENSE
446b81cf4ea652806fd50e87468d0d70 *NAMESPACE
2b71fd563af41290de6b175d4988cdf4 *NEWS.md
d111bb7ebefc511b43062b59a230f16c *R/check_that.R
69a15c437c4a22d31ba281b606a2fecd *R/checkthat-package.R
dba688c07212453e97bf1b621cfdcde8 *R/cli_output.R
13b56b21cf7ee4b5fa5a375eb190bd50 *R/quantifiers.R
4a596ff541a32c0017ae2a4babc8d3cb *R/utils-typechecks.R
21c00a080f3b63727d7d992c4d642576 *README.md
392e2f8429a6bd5d42b521db86b16184 *build/vignette.rds
844769f406b00030738ca6c4b3188d4d *inst/doc/checkthat.R
43be881390a11246adb20fc47c520b23 *inst/doc/checkthat.Rmd
bb4041f90da6258e60bcdf1006ebf559 *inst/doc/checkthat.html
d45b345d69e0d2f332f2dc0dc4eb2870 *man/at_least.Rd
a7337084730e71dd8b7e070202570de8 *man/at_most.Rd
5f6f2b7bf7fc732e19c3cbc08666f299 *man/check_that.Rd
8a5838fb3586ed3463f31358cd67c7f1 *man/checkthat-package.Rd
8367c2181f158992a712fa9d58fce7bf *man/exactly_equal.Rd
502a5f8dd6ba90060101596366cb7d58 *man/figures/README-pressure-1.png
a1cbaf3f328e8d74e747faacf640c7fc *man/figures/lifecycle-archived.svg
6f521fb1819410630e279d1abf88685a *man/figures/lifecycle-defunct.svg
391f696f961e28914508628a7af31b74 *man/figures/lifecycle-deprecated.svg
691b1eb2aec9e1bec96b79d11ba5e631 *man/figures/lifecycle-experimental.svg
405e252e54a79b33522e9699e4e9051c *man/figures/lifecycle-maturing.svg
f41ed996be135fb35afe00641621da61 *man/figures/lifecycle-questioning.svg
306bef67d1c636f209024cf2403846fd *man/figures/lifecycle-soft-deprecated.svg
ed42e3fbd7cc30bc6ca8fa9b658e24a8 *man/figures/lifecycle-stable.svg
bf2f1ad432ecccee3400afe533404113 *man/figures/lifecycle-superseded.svg
845da2913739aca4752ad65023160355 *man/for_case.Rd
9ad2e1c3a5c8f2a4a465c87d3591f841 *man/is_count.Rd
c928b74f7f164828eba318e924a22152 *man/is_integerlike.Rd
eb0c27e7462c88388902db731a505e44 *man/is_logical_vec.Rd
cc0eab939c12d4759b99117101bcd43f *man/is_proportion.Rd
178fae0cf0d34095789501c65f694455 *man/less_than.Rd
581c4cdcd7b23e3c874469be71e9b7df *man/more_than.Rd
f58eaa936f691a828c3cb65a061be584 *man/prop.Rd
622b3180b085bf5633a00fd435776750 *man/some_of.Rd
aa80795e93697d571ca475466a4b7077 *man/validate_count.Rd
1059b7260f062d3be904ee82a0f7e8ad *man/validate_logical_vec.Rd
9d5d28030a180b3e26b1e62d55887de4 *man/validate_proportion.Rd
382dc1679890533934cd4077cc6c25e7 *man/whenever.Rd
3f42afafa0047175a88d70071bb347f4 *tests/testthat.R
03f1ee15ed52ba459ddbfa371b61d0bd *tests/testthat/_snaps/cli_output.md
7ffc73882ff68567ee5b082bf24bb71a *tests/testthat/test-check_that.R
f010b5026f33a849328fc0e837edeaff *tests/testthat/test-cli_output.R
f1f7ae96f9434a2909bfd7f5b8012f21 *tests/testthat/test-quantifiers.R
6852d271864ff0e3112d3585592f68d2 *tests/testthat/test-utils-typechecks.R
43be881390a11246adb20fc47c520b23 *vignettes/checkthat.Rmd
22 changes: 22 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by roxygen2: do not edit by hand

export(at_least)
export(at_most)
export(check_that)
export(exactly_equal)
export(for_case)
export(is_count)
export(is_integerlike)
export(is_logical_vec)
export(is_proportion)
export(less_than)
export(more_than)
export(prop)
export(some_of)
export(validate_count)
export(validate_logical_vec)
export(validate_proportion)
export(whenever)
import(rlang)
importFrom(glue,glue)
importFrom(lifecycle,deprecated)
14 changes: 14 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# checkthat 0.1.0

* Initial CRAN submission.

# checkthat 0.0.0.9000

* Initial Github submission.

## Major changes

* Implemented check_that() function for evaluating dataframes.
* Implemented helper functions (e.g., some_of(), whenever()) to simplify the test/check creation process.


75 changes: 75 additions & 0 deletions R/check_that.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#' Check that assertions about a dataframe are true/false
#'
#' This function allows you to test whether a set of assertions about a
#' dataframe are true and to print the results of those tests. It is
#' particularly useful for quality control and data validation.
#'
#' The \code{check_that()} function is designed to work with both base R's
#' existing logical functions, as well as several new functions provided in the
#' checkthat package (see See Also below).
#'
#' In addition, it also provides a data pronoun, \code{.d}. This is a copy of
#' the \code{.data} dataframe provided as the first argument and is useful for
#' testing not only features of specific rows or columns, but of the entire
#' dataframe, see examples.
#'
#' @param .data A dataframe to be tested.
#' @param ... One or more conditions to test on the dataframe. Each condition
#' should be expressed as a logical expression that evaluates to a
#' single \code{TRUE} or \code{FALSE} value (e.g., \code{all(x < 3)},
#' \code{!any(is.na(x))}).
#' @param print Logical. If \code{TRUE}, the results of the tests will be
#' printed.
#' @param raise_error Logical. If \code{TRUE}, an error will be thrown if any
#' test fails. If \code{FALSE}, the evaluation will
#' continue even if tests fail. Disabling errors can
#' sometimes be useful for debugging, but should generally be
#' avoided in finalized checks/tests.
#' @param encourage Logical. If \code{TRUE}, encouraging messages will be
#' displayed for tests that pass.
#'
#' @returns (invisibly) the original, unmodified \code{.data} dataframe.
#'
#' @seealso \code{\link{some_of}}, \code{\link{whenever}},
#' \code{\link{for_case}}
#'
#' @examples
#' example_data <- data.frame(x = 1:5, y = 6:10)
#'
#' # Test a dataframe for specific conditions
#' example_data |>
#' check_that(
#' all(x > 0),
#' !any(y < 5)
#' )
#'
#' # Use .d pronoun to test aspect of entire dataframe
#' example_data |>
#' check_that(
#' nrow(.d) == 5,
#' "x" %in% names(.d)
#' )
#'
#' @export
check_that <- function(.data, ..., print = TRUE, raise_error = TRUE,
encourage = TRUE) {
# TODO: add support for grouped data frames

dots <- rlang::enquos(...)

data_mask <- rlang::as_data_mask(.data)
data_mask$.d <- .data

test_labs <- purrr::map_chr(dots, .f = rlang::as_label)
test_results <- purrr::map_lgl(dots, .f = ~ rlang::eval_tidy(.x, data_mask))

if (print) {
cli_print_checks(test_results, test_labs, encourage = encourage)
}

if (raise_error & any(test_results != TRUE)) {
cli_throw_test_error()
}

invisible(.data)
}
9 changes: 9 additions & 0 deletions R/checkthat-package.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#' @keywords internal
"_PACKAGE"

## usethis namespace: start
#' @import rlang
#' @importFrom glue glue
#' @importFrom lifecycle deprecated
## usethis namespace: end
NULL
172 changes: 172 additions & 0 deletions R/cli_output.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#' Internal Function to Customize the CLI Theme for checkthat Messages
#'
#' This is an internal function that is not intended for external use. It
#' customizes the Command Line Interface (CLI) theme for messages displayed
#' by the checkthat package.
#'
#' @keywords internal
#' @noRd
#'
#' @returns A customized CLI theme for checkthat messages.
checkthat_cli_theme <- function() {
theme <- cli::builtin_theme()
theme[["h1"]][["color"]] <- "grey40"
theme[[".alert-success"]][["color"]] <- "grey40"
theme[[".alert-danger"]][["color"]] <- "grey40"
theme[["body"]][["color"]] <- "grey40"

theme
}

#' Internal Function to Retrieve a Random Encouraging Message
#'
#' This is an internal function that is not intended for external use.
#' It retrieves a random encouraging message from a predefined list of messages.
#'
#' @keywords internal
#' @noRd
#'
#' @returns A randomly selected string containing an encouraging message.
encouraging_message <- function() {
encouraging_messages <- c(
"You've got this!",
"Believe in yourself",
"Keep pushing forward",
"Every step is progress",
"Stay determined, success is near",
"Challenges help you grow",
"You're making it happen!",
"Keep your focus, you'll get there",
"Trust the process",
"Hard work pays off",
"Stay positive, stay persistent",
"Perseverance leads to success",
"Small victories count"
)

chosen_message <- sample(encouraging_messages, size = 1)

chosen_message
}

#' Internal Function to Display a Success Message in the CLI
#'
#' This is an internal function that is not intended for external use. It
#' displays a success message in the Command Line Interface (CLI) using the
#' customized checkthat theme.
#'
#' @returns \value{None}
#'
#' @keywords internal
#' @noRd
cli_check_success <- function() {
cli::start_app(theme = checkthat_cli_theme())
cli::cli_alert_success("all data checks passing")
}

#' Internal Function to Add Encouraging Messages to the CLI
#'
#' This is an internal function that is not intended for external use. It adds
#' encouraging messages to the Command Line Interface (CLI) using the customized
#' checkthat theme.
#'
#' @param msg A custom message to display. If not provided, a random encouraging message will be selected.
#' @param p The probability of displaying the message. Default is 0.33.
#'
#' @keywords internal
#' @noRd
#'
#' @returns (invisibly) The unmodified \code{msg} string from above.
cli_add_encouragement <- function(msg = encouraging_message(), p = .33) {
if (stats::runif(1) < p) {
cli::start_app(theme = checkthat_cli_theme())
cli::cli_text("")
cli::cli_text(msg)
}

invisible(msg)
}

#' Internal Function to Trigger a Test Error in the CLI
#'
#' This is an internal function that is not intended for external use. It
#' triggers a test error message in the Command Line Interface (CLI) using the
#' customized checkthat theme.
#'
#' @returns \value{None}
#'
#' @keywords internal
#' @noRd
cli_throw_test_error <- function() {
cli::start_app(theme = checkthat_cli_theme())
cli::cli_text("")
cli::cli_text("")
cli::cli_abort("At least one data check failed.")
}

#' Internal Function to Display a Summary of Test Results in the CLI
#'
#' This is an internal function that is not intended for external use. It
#' displays a summary of test results in the Command Line Interface (CLI) using
#' the customized checkthat theme.
#'
#' @param test_results A logical vector representing the results of data checks.
#' @param test_labs A character vector containing labels for the data checks.
#'
#' @keywords internal
#' @noRd
#'
#' @returns (invisibly) A named character vector of check results.
cli_check_summary <- function(test_results, test_labs) {
if (length(test_results) != length(test_labs)) {
stop("length(test_results) != length(test_labs)")
}

cli::start_app(theme = checkthat_cli_theme())
cli::cli_h1("Data Checks")
cli::cli_text("")

for (i in seq_along(test_results)) {
result <- "{test_labs[i]} --> {test_results[i]}"

if (test_results[i]) {
cli::cli_alert_success(result)
} else {
cli::cli_alert_danger(result)
}
}

cli::cli_h1("")

check_summary <- as.list(test_results) |>
purrr::set_names(test_labs)

invisible(check_summary)
}

#' Internal Function to Print Data Check Results in the CLI
#'
#' This is an internal function that is not intended for external use. It prints
#' the results of data checks in the Command Line Interface (CLI) using the
#' customized checkthat theme.
#'
#' @param test_results A logical vector representing the results of data checks.
#' @param test_labs A character vector containing labels for the data checks.
#' @param encourage Logical. If \code{TRUE}, encouraging messages will be
#' displayed when tests pass.
#'
#' @returns \value{None}
#'
#' @keywords internal
#' @noRd
cli_print_checks <- function(test_results, test_labs, encourage = TRUE) {
if (all(test_results) == TRUE) {
cli_check_success()
} else {
cli_check_summary(test_results, test_labs)

if (encourage) {
cli_add_encouragement()
}
}
}

0 comments on commit 092af94

Please sign in to comment.