# just some set up a <- 1 alist <- list(a=c(1,2,3), b=c(4,5,6)) our.iris <- iris our.iris.2 <- our.iris our.iris.2[106,1] <- 7 our.iris.3 <- our.iris.2 our.iris.3[c(118, 119, 123, 132, 131, 136), 1] <- 7 exmpl.data <- data.frame(x=c(8, 9, 6, 5, 9, 5, 6, 7, 8, 9, 6, 5, 5, 6, 7), y=c(82, 91, 61, 49, 40, 49, 57, 74, 78, 90, 61, 49, 51, 62, 68)) nexmpl.data <- exmpl.data nexmpl.data[12,2] <- NA mnexmpl.data <- nexmpl.data mnexmpl.data[12,1] <- NA nanmnexmpl.data <- mnexmpl.data nanmnexmpl.data[10,1] <- 0/0 test.df <- data.frame(x = c(0, 1, 2)) test.df2 <- data.frame(x = c(0, 1, 2), y = c(2, 1.5, 1), z = c(0,NA, -1)) # custom error (or success) messages not.helpful <- function(message, ...){ stop("unspecified error", call.=FALSE) } give.validation <- function(data, ...){ return("great job!") } just.show.error <- function(err, ...){ lapply(err, summary) } # helper functions for verifying success_append results success_result <- function(verb, the_call, columns, row_redux_call, description) { row_redux_message <- "" if (!is.na(row_redux_call)) row_redux_message <- paste0(" on ", row_redux_call, " row reduction") msg <- paste0("verification [", the_call, "]", row_redux_message, " passed!") success <- list( verb = verb, message = msg, call = the_call, columns = columns, row_redux_call = row_redux_call, description = description ) class(success) <- c("assertr_success", "success", "condition") list(success) } get_assertr_success <- function(assertion) { attr(assertion, "assertr_success") } ############### verify ############### test_that("verify returns data if verification passes", { expect_equal(verify(mtcars, drat > 2), mtcars) expect_equal(verify(mtcars, mtcars$drat > 2), mtcars) expect_equal(verify(mtcars, mtcars$drat > 2), mtcars) expect_equal(verify(mtcars, nrow(mtcars) > 30), mtcars) expect_equal(verify(mtcars, am %in% c(0,1,2)), mtcars) expect_equal(verify(mtcars, am %in% c(0,1)), mtcars) # looks to parent frame scope? expect_equal(verify(mtcars, a > 0), mtcars) expect_equal(verify(mtcars, nrow(iris) > 140), mtcars) expect_equal(verify(alist, length(a) > 0), alist) # respects scoping rules? expect_equal(verify(alist, length(a) > 2), alist) expect_equal(verify(alist, length(a) > 2 && length(b) > 2), alist) expect_equal(verify(alist, a >= 1 & b > 2), alist) expect_equal(verify(alist, a > 2 | b > 2), alist) expect_equal(verify(alist, 3 > 2), alist) }) test_that("verify returns TRUE if verification passes (and we use `success_logical`)", { expect_true(verify(mtcars, drat > 2, success_fun=success_logical)) expect_true(verify(mtcars, mtcars$drat > 2, success_fun=success_logical)) expect_true(verify(mtcars, mtcars$drat > 2, success_fun=success_logical)) expect_true(verify(mtcars, nrow(mtcars) > 30, success_fun=success_logical)) expect_true(verify(mtcars, am %in% c(0,1,2), success_fun=success_logical)) expect_true(verify(mtcars, am %in% c(0,1), success_fun=success_logical)) # looks to parent frame scope? expect_true(verify(mtcars, a > 0, success_fun=success_logical)) expect_true(verify(mtcars, nrow(iris) > 140, success_fun=success_logical)) expect_true(verify(alist, length(a) > 0, success_fun=success_logical)) # respects scoping rules? expect_true(verify(alist, length(a) > 2, success_fun=success_logical)) expect_true(verify(alist, length(a) > 2 && length(b) > 2, success_fun=success_logical)) expect_true(verify(alist, a >= 1 & b > 2, success_fun=success_logical)) expect_true(verify(alist, a > 2 | b > 2, success_fun=success_logical)) expect_true(verify(alist, 3 > 2, success_fun=success_logical)) }) test_that("verify returns success results if verification passes (and we use `success_append`)", { expect_equal( get_assertr_success(verify(mtcars, drat > 2, success_fun=success_append)), success_result("verify", "drat > 2", NA, NA, NA)) expect_equal( get_assertr_success(verify(mtcars, mtcars$drat > 2, success_fun=success_append)), success_result("verify", "mtcars$drat > 2", NA, NA, NA)) expect_equal( get_assertr_success(verify(mtcars, mtcars$drat > 2, success_fun=success_append)), success_result("verify", "mtcars$drat > 2", NA, NA, NA)) expect_equal( get_assertr_success(verify(mtcars, nrow(mtcars) > 30, success_fun=success_append)), success_result("verify", "nrow(mtcars) > 30", NA, NA, NA)) expect_equal( get_assertr_success(verify(mtcars, am %in% c(0,1,2), success_fun=success_append)), success_result("verify", "am %in% c(0, 1, 2)", NA, NA, NA)) expect_equal( get_assertr_success(verify(mtcars, am %in% c(0,1), success_fun=success_append)), success_result("verify", "am %in% c(0, 1)", NA, NA, NA)) # looks to parent frame scope? expect_equal( get_assertr_success(verify(mtcars, a > 0, success_fun=success_append)), success_result("verify", "a > 0", NA, NA, NA)) expect_equal( get_assertr_success(verify(mtcars, nrow(iris) > 140, success_fun=success_append)), success_result("verify", "nrow(iris) > 140", NA, NA, NA)) expect_equal( get_assertr_success(verify(alist, length(a) > 0, success_fun=success_append)), success_result("verify", "length(a) > 0", NA, NA, NA)) # respects scoping rules? expect_equal( get_assertr_success(verify(alist, length(a) > 2, success_fun=success_append)), success_result("verify", "length(a) > 2", NA, NA, NA)) expect_equal( get_assertr_success(verify(alist, length(a) > 2 && length(b) > 2, success_fun=success_append)), success_result("verify", "length(a) > 2 && length(b) > 2", NA, NA, NA)) expect_equal( get_assertr_success(verify(alist, a >= 1 & b > 2, success_fun=success_append)), success_result("verify", "a >= 1 & b > 2", NA, NA, NA)) expect_equal( get_assertr_success(verify(alist, a > 2 | b > 2, success_fun=success_append)), success_result("verify", "a > 2 | b > 2", NA, NA, NA)) expect_equal( get_assertr_success(verify(alist, 3 > 2, success_fun=success_append)), success_result("verify", "3 > 2", NA, NA, NA)) }) test_that("verify performs custom success function if verification passes", { expect_equal(verify(mtcars, drat > 2, success_fun=give.validation), "great job!") expect_equal(verify(mtcars, mtcars$drat > 2, function(x, ...){return("noice!")}), "noice!") }) test_that("verify raises error if verification fails", { expect_equal(verify(mtcars, drat > 3, error_fun = error_logical), FALSE) expect_output(verify(mtcars, drat > 3, error_fun = just.show.error), "verification \\[drat > 3\\] failed! \\(4 failures\\)") expect_equal(verify(mtcars, nrow(mtcars) > 34, error_fun = error_logical), FALSE) expect_output(verify(mtcars, nrow(mtcars) > 34, error_fun = just.show.error), "verification \\[nrow\\(mtcars\\) > 34\\] failed! \\(1 failure\\)") expect_equal(verify(mtcars, am %in% c(1,2), error_fun = error_logical), FALSE) expect_output(verify(mtcars, am %in% c(1,2), error_fun = just.show.error), "verification \\[am %in% c\\(1, 2\\)\\] failed! \\(19 failures\\)") # looks to parent frame scope? expect_equal(verify(mtcars, a < 0, error_fun = error_logical), FALSE) expect_output(verify(mtcars, a < 0, error_fun = just.show.error), "verification \\[a < 0\\] failed! \\(1 failure\\)") # respects scoping rules? expect_equal(verify(alist, length(a) == 1, error_fun = error_logical), FALSE) expect_output(verify(alist, length(a) == 1, error_fun = just.show.error), "verification \\[length\\(a\\) == 1\\] failed! \\(1 failure\\)") expect_equal(verify(alist, length(a) > 4, error_fun = error_logical), FALSE) expect_output(verify(alist, length(a) > 4, error_fun = just.show.error), "verification \\[length\\(a\\) > 4\\] failed! \\(1 failure\\)") expect_output(verify(alist, length(a) > 2 && length(b) > 3, error_fun = just.show.error), "verification \\[length\\(a\\) > 2 && length\\(b\\) > 3\\] failed! \\(1 failure\\)") expect_output(verify(alist, a >= 2 | b > 4, error_fun = just.show.error), "verification \\[a >= 2 | b > 4\\] failed! \\(1 failure\\)") expect_output(verify(alist, 2 > 4, error_fun = just.show.error), "verification \\[2 > 4\\] failed! \\(1 failure\\)") # NA values don't compare TRUE expect_output(verify(test.df2, z > -2, error_fun = just.show.error), "verification \\[z > -2\\] failed! \\(1 failure\\)") }) test_that("verify breaks appropriately", { expect_error(verify(4 > 2), "argument \"expr\" is missing, with no default") expect_error(verify(mtcars), "argument \"expr\" is missing, with no default") expect_error(verify(MTCARS, 2 > 1), "object 'MTCARS' not found") expect_warning(expect_warning( verify(mtcars, 1), "coercing argument of type 'double' to logical"), "The result of evaluating '1' is not a logical vector" ) expect_error(suppressWarnings(verify(mtcars, "1")), "missing value where TRUE/FALSE needed") expect_error(verify(mtcars, 1 > 0, "tree"), "could not find function \"success_fun\"") expect_error(verify(mtcars, d > 1), "object 'd' not found") }) test_that("verify works within functions", { my_verify <- function(data, expr, success_fun) { verify(data, !!rlang::enexpr(expr), success_fun=success_fun) } expect_true(my_verify(mtcars, drat > 2, success_fun=success_logical)) }) test_that("verify works with long predicates (fix #80)", { my_data <- data.frame(COMMENT=c("foo", "bar", "baz", "Positive Pre-dose"), USUBJID = "ABCDEFGHIJKLMNOPQRTSU", stringsAsFactors=FALSE) expect_output( expect_error( verify(my_data, is.na(COMMENT) | (COMMENT %in% "Positive Pre-dose" & USUBJID %in% "ABCDEFGHIJKLMNOPQRTSU")), "assertr stopped execution" ), regexp='is.na(COMMENT) | (COMMENT %in% "Positive Pre-dose" & USUBJID %in% "ABCDEFGHIJKLMNOPQRTSU")', fixed=TRUE ) }) test_that("skip_chain_opts doesn't affect functionality outside chain for verify", { expect_equal(verify(mtcars, mtcars$drat > 2, skip_chain_opts=TRUE), mtcars) expect_equal(verify(mtcars, nrow(mtcars) > 30, skip_chain_opts=TRUE), mtcars) expect_true(verify(mtcars, mtcars$drat > 2, success_fun=success_logical, skip_chain_opts=TRUE)) expect_true(verify(mtcars, nrow(mtcars) > 30, success_fun=success_logical, skip_chain_opts=TRUE)) expect_equal(verify(mtcars, drat > 3, error_fun=error_logical, skip_chain_opts=TRUE), FALSE) expect_output(verify(mtcars, drat > 3, error_fun=just.show.error, skip_chain_opts=TRUE), "verification \\[drat > 3\\] failed! \\(4 failures\\)") }) test_that("verify says when a zero-length result means nothing was checked", { # a misspelled column, an empty subset, and a list with an empty element expect_warning(verify(mtcars, mtcars$zzz > 0), "The result of evaluating 'mtcars$zzz > 0' has length zero, so nothing was checked", fixed = TRUE) expect_warning(verify(mtcars, mpg[mpg > 100] > 0), "The result of evaluating 'mpg[mpg > 100] > 0' has length zero, so nothing was checked", fixed = TRUE) expect_warning(verify(list(a=numeric(0)), a > 0), "The result of evaluating 'a > 0' has length zero, so nothing was checked", fixed = TRUE) # the data still comes back expect_equal(suppressWarnings(verify(mtcars, mtcars$zzz > 0)), mtcars) # a data.frame with no rows has nothing to check, which is not worth a warning expect_silent(mtcars %>% dplyr::filter(cyl == 5) %>% verify(mpg > 10)) expect_silent(verify(mtcars[0, ], is_uniq(mpg))) expect_equal(verify(mtcars[0, ], mpg > 10), mtcars[0, ]) }) test_that("verify lets `.` stand for the data, with or without a magrittr pipe", { # `mtcars |> verify(nrow(.) > 10)` is the same call as `verify(mtcars, nrow(.) > 10)`: # the native pipe does not define `.`, so it is written that way here (which # also keeps this file readable by versions of R that have no native pipe) dotted <- data.frame(a=1:3) dotted[["."]] <- c(10, 20, 30) expect_equal(mtcars %>% verify(nrow(.) > 10), mtcars) expect_equal(verify(mtcars, .data$mpg > 0), mtcars) # a column that is itself called `.` comes first expect_true(verify(dotted, . > 5, success_fun=success_logical)) expect_equal(verify(mtcars, nrow(.) > 10), mtcars) expect_equal(verify(mtcars, nrow(.) > 100, error_fun=error_logical), FALSE) expect_output(verify(mtcars, nrow(.) > 100, error_fun=just.show.error), "verification [nrow(.) > 100] failed! (1 failure)", fixed = TRUE) # it is the data being verified, also inside another pipeline that has its own `.` expect_equal(suppressWarnings(list(1) %>% { verify(mtcars, nrow(.) > 100, error_fun=error_logical) }), FALSE) # in a function, on a list, and next to variables from the calling code rows.of <- function(some.data) verify(some.data, nrow(.) == 32) expect_equal(rows.of(mtcars), mtcars) expect_true(verify(list(a=1:3), length(.) == 1, success_fun=success_logical)) at.least <- 5 expect_equal(verify(mtcars, nrow(.) > at.least), mtcars) }) ###################################### ############### assert ############### test_that("assert returns data if verification passes", { expect_equal(assert(mtcars, in_set(0,1), vs, am), mtcars) expect_equal(assert(mtcars, within_bounds(3,5), gear), mtcars) expect_equal(assert(mtcars, is.numeric, mpg:carb), mtcars) expect_equal(assert(mtcars, not_na, vs), mtcars) expect_equal(assert(mtcars, not_na, mpg:carb), mtcars) # lambdas expect_equal(assert(mtcars, function(x) x%%1==0, cyl, vs, am, gear, carb), mtcars) expect_equal(assert(mtcars, function(x) if(x%%1!=0) return(FALSE), gear), mtcars) expect_equal(assert(iris, function(x) nchar(as.character(x)) > 5, Species), iris) }) test_that("assert returns TRUE if verification passes (w/ `success_logical`)", { expect_true(assert(mtcars, in_set(0,1), vs, am, success_fun=success_logical)) expect_true(assert(mtcars, within_bounds(3,5), gear, success_fun=success_logical)) expect_true(assert(mtcars, is.numeric, mpg:carb, success_fun=success_logical)) expect_true(assert(mtcars, not_na, vs, success_fun=success_logical)) expect_true(assert(mtcars, not_na, mpg:carb, success_fun=success_logical)) # lambdas # expect_true(assert(mtcars, function(x) x%%1==0, cyl, vs, am, gear, carb, # success_fun=success_logical)) expect_true(assert(mtcars, function(x) if(x%%1!=0) return(FALSE), gear, success_fun=success_logical)) expect_true(assert(iris, function(x) nchar(as.character(x)) > 5, Species, success_fun=success_logical)) }) test_that("assert returns correct result if verification passes (w/ `success_append`)", { expect_equal( get_assertr_success(assert(mtcars, in_set(0,1), vs, am, success_fun=success_append)), success_result("assert", "in_set(0, 1)", c("vs", "am"), NA, NA)) expect_equal( get_assertr_success(assert(mtcars, within_bounds(3,5), gear, success_fun=success_append)), success_result("assert", "within_bounds(3, 5)", "gear", NA, NA)) expect_equal( get_assertr_success(assert(mtcars, is.numeric, mpg:carb, success_fun=success_append)), success_result("assert", "is.numeric", colnames(mtcars), NA, NA)) expect_equal( get_assertr_success(assert(mtcars, not_na, vs, success_fun=success_append)), success_result("assert", "not_na", "vs", NA, NA)) expect_equal( get_assertr_success(assert(mtcars, not_na, mpg:carb, success_fun=success_append)), success_result("assert", "not_na", colnames(mtcars), NA, NA)) expect_equal( get_assertr_success(assert(mtcars, function(x) x%%1==0, cyl, vs, am, gear, carb, success_fun=success_append)), success_result("assert", "function(x) x%%1 == 0", c("cyl", "vs", "am", "gear", "carb"), NA, NA)) expect_equal( get_assertr_success(assert(mtcars, function(x) if(x%%1!=0) return(FALSE), gear, success_fun=success_append)), success_result("assert", "function(x) if (x%%1 != 0) return(FALSE)", "gear", NA, NA)) expect_equal( get_assertr_success(assert(iris, function(x) nchar(as.character(x)) > 5, Species, success_fun=success_append)), success_result("assert", "function(x) nchar(as.character(x)) > 5", "Species", NA, NA)) }) test_that("assert performs custom success function if verification passes", { expect_equal(assert(mtcars, not_na, mpg:carb, success_fun=give.validation), "great job!") expect_equal(assert(mtcars, within_bounds(3,5), gear, success_fun=function(x, ...) {return("noice!")}), "noice!") }) test_that("assert raises error if verification fails", { expect_equal(assert(mtcars, within_bounds(3.5,4.5), gear, error_fun = error_logical), FALSE) expect_output(assert(mtcars, within_bounds(3.5,4.5), gear, error_fun = just.show.error), "Column 'gear' violates assertion 'within_bounds\\(3.5, 4.5\\)' 20 times.*") expect_equal(assert(mtcars, within_bounds(3,5), gear, carb, error_fun = error_logical), FALSE) expect_output(assert(mtcars, within_bounds(3,5), gear, carb, error_fun = just.show.error), "Column 'carb' violates assertion 'within_bounds\\(3, 5\\)' 19 times") expect_equal(assert(mtcars, within_bounds(3.5, 4.5), carb, gear, error_fun = error_logical), FALSE) expect_output(assert(mtcars, within_bounds(3.5, 4.5), carb, gear, error_fun = just.show.error), "Column 'carb' violates assertion 'within_bounds\\(3.5, 4.5\\)' 22 times.+Column 'gear' violates assertion 'within_bounds\\(3.5, 4.5\\)' 20 times") }) test_that("assert raises *custom error* if verification fails", { expect_error(assert(mtcars, within_bounds(3.5,4.5), gear, error_fun=not.helpful), "unspecified error") expect_error(assert(mtcars, within_bounds(3,5), gear, carb, error_fun=not.helpful), "unspecified error") }) test_that("assert breaks appropriately", { expect_error(assert(in_set(0,1), mtcars$vs), "assert requires columns to be selected. Check number of arguments") expect_error( object = { assert(mtcars, in_set(0,1), vs, tree) }, regexp = "Column `tree` doesn't exist", class = "error" ) expect_error(assert(mtcars, in_set(0,1), vs, "tree")) expect_error(assert("tree"), "argument \"predicate\" is missing, with no default") }) test_that("skip_chain_opts doesn't affect functionality outside chain for assert", { expect_equal(assert(mtcars, in_set(0,1), vs, am, skip_chain_opts=TRUE), mtcars) expect_equal(assert(mtcars, within_bounds(3,5), gear, skip_chain_opts=TRUE), mtcars) expect_true(assert(mtcars, in_set(0,1), vs, am, success_fun=success_logical, skip_chain_opts=TRUE)) expect_true(assert(mtcars, within_bounds(3,5), gear, success_fun=success_logical, skip_chain_opts=TRUE)) expect_equal(assert(mtcars, within_bounds(3.5,4.5), gear, error_fun=error_logical, skip_chain_opts=TRUE), FALSE) expect_output(assert(mtcars, within_bounds(3.5,4.5), gear, error_fun=just.show.error, skip_chain_opts=TRUE), "Column 'gear' violates assertion 'within_bounds\\(3.5, 4.5\\)' 20 times.*") }) test_that("assert works with single row data.frames", { single_row_data <- head(mtcars, 1) expect_equal(assert(single_row_data, within_bounds(10,30), disp, error_fun = error_logical), FALSE) expect_output(assert(single_row_data, within_bounds(10,30), disp, error_fun = just.show.error), "Column 'disp' violates assertion 'within_bounds\\(10, 30\\)' 1 time.*") expect_equal(assert(single_row_data, within_bounds(10,30), disp, mpg, error_fun = error_logical), FALSE) expect_output(assert(single_row_data, within_bounds(10,30), disp, mpg, error_fun = just.show.error), "Column 'disp' violates assertion 'within_bounds\\(10, 30\\)' 1 time.*") }) test_that("assert applies custom predicates element-wise on a single column", { contacts <- data.frame(email=c("a@b.com", "not-an-email", "also bad"), zip=c("12345", "123", ""), stringsAsFactors=FALSE) has.at <- function(x) grepl("@", x) long.enough <- function(x) nchar(x) >= 5 improper.has.at <- function(x) if(!grepl("@", x)) return(FALSE) expect_equal(assert(contacts, has.at, email, error_fun = error_logical), FALSE) expect_output(assert(contacts, has.at, email, error_fun = just.show.error), "Column 'email' violates assertion 'has.at' 2 times") expect_equal(assert(contacts, long.enough, zip, error_fun = error_logical), FALSE) expect_output(assert(contacts, long.enough, zip, error_fun = just.show.error), "Column 'zip' violates assertion 'long.enough' 2 times") expect_equal(assert(contacts, improper.has.at, email, error_fun = error_logical), FALSE) }) test_that("assert and assert_rows stop when a predicate returns a zero-length value", { limits <- list(max_mpg=30) # a misspelled list element is NULL, so the comparison has length zero expect_error(assert(mtcars, function(x) x <= limits$max_mgp, mpg), "predicate 'function(x) x <= limits$max_mgp' returned a zero-length value", fixed = TRUE) # grep (unlike grepl) returns integer(0) when there is no match expect_error(assert(iris, function(x) grep("virginica", x), Species), "predicate 'function(x) grep(\"virginica\", x)' returned a zero-length value", fixed = TRUE) expect_error(assert_rows(mtcars, rowSums, function(x) x <= limits$max_mgp, vs, am), "predicate 'function(x) x <= limits$max_mgp' returned a zero-length value", fixed = TRUE) # dropping NAs inside the predicate leaves nothing to test for an NA element expect_error(assert(test.df2, function(x) x[!is.na(x)] > -2, z), "predicate 'function(x) x[!is.na(x)] > -2' returned a zero-length value", fixed = TRUE) }) test_that("an NA from a predicate counts as a violation", { # test.df2$z is c(0, NA, -1); the row sums of test.df2 are c(2, NA, 2) gen <- function(a.vector) function(x) x > -5 row.gen <- function(a.vector) function(x) x > 0 expect_equal(assert(test.df2, function(x) x > -5, z, error_fun = error_logical), FALSE) expect_output(assert(test.df2, function(x) x > -5, z, error_fun = just.show.error), "Column 'z' violates assertion 'function(x) x > -5' 1 time", fixed = TRUE) expect_output(assert(test.df2, function(x) x >= 0, z, error_fun = just.show.error), "Column 'z' violates assertion 'function(x) x >= 0' 2 times", fixed = TRUE) expect_output(assert(test.df2, is_uniq, z, error_fun = just.show.error), "Column 'z' violates assertion 'is_uniq' 1 time", fixed = TRUE) expect_output(assert_rows(test.df2, rowSums, function(x) x > 0, x:z, error_fun = just.show.error), "Data frame row reduction 'rowSums' violates predicate 'function(x) x > 0' 1 time", fixed = TRUE) expect_output(insist(test.df2, gen, z, error_fun = just.show.error), "Column 'z' violates assertion 'gen' 1 time", fixed = TRUE) expect_output(insist_rows(test.df2, rowSums, row.gen, x:z, error_fun = just.show.error), "Data frame row reduction 'rowSums' violates predicate 'row.gen' 1 time", fixed = TRUE) # predicates that handle NA themselves are unaffected expect_equal(assert(test.df2, within_bounds(-5, 5), z), test.df2) }) test_that("long predicate calls and verify expressions are reported as one string (#88)", { long.set <- in_set("alpha-alpha-alpha", "bravo-bravo-bravo", "charlie-charlie", "delta-delta-delta", "echo-echo-echo-echo", "foxtrot-foxtrot") long.bounds <- within_bounds(lower.bound=0, upper.bound=1, include.lower=TRUE, include.upper=TRUE, allow.na=TRUE) expect_equal(length(attr(long.set, "call")), 1) expect_equal(length(attr(long.bounds, "call")), 1) expect_equal(length(attr(within_n_sds(3, include.lower=TRUE, include.upper=TRUE, allow.na=TRUE, check.class=TRUE), "call")), 1) expect_equal(length(attr(within_n_mads(3, include.lower=TRUE, include.upper=TRUE, allow.na=TRUE, check.class=TRUE), "call")), 1) # two violations used to be labelled with one half of the call each two.bad <- data.frame(s=c("alpha-alpha-alpha", "x", "y"), stringsAsFactors=FALSE) errs <- assert(two.bad, long.set, s, error_fun = error_df_return) expect_equal(length(unique(errs$predicate)), 1) errs <- verify(mtcars, mpg > 33 & cyl %in% c(4, 6, 8) & disp > 100 & hp > 50 & drat > 1 & wt > 1 & qsec > 10, error_fun = error_return) expect_equal(length(errs[[1]]$message), 1) # three violations could not be matched to the two halves at all three.bad <- data.frame(s=c("alpha-alpha-alpha", "x", "y", "z"), stringsAsFactors=FALSE) errs <- assert(three.bad, long.set, s, error_fun = error_df_return) expect_equal(nrow(errs), 3) }) ###################################### ############### assert_rows ############### test_that("assert_rows returns data if verification passes", { expect_equal(assert_rows(mtcars, rowSums, within_bounds(0,2), vs, am), mtcars) expect_equal(assert_rows(mtcars, num_row_NAs, within_bounds(0,.1), dplyr::everything()), mtcars) expect_equal(assert_rows(mtcars, rowSums, within_bounds(5,16), cyl, carb), mtcars) expect_equal(assert_rows(mnexmpl.data, num_row_NAs, within_bounds(0,2), dplyr::everything()), mnexmpl.data) expect_equal(assert_rows(nexmpl.data, num_row_NAs, function(x) x < 2, dplyr::everything()), nexmpl.data) expect_equal(assert_rows(mtcars, rowSums, function(x) if(x>16) return(FALSE), carb, cyl), mtcars) }) test_that("assert_rows returns TRUE if verification passes (w/ `success_logical`", { expect_true(assert_rows(mtcars, rowSums, within_bounds(0,2), vs, am, success_fun=success_logical)) expect_true(assert_rows(mtcars, num_row_NAs, within_bounds(0,.1), dplyr::everything(), success_fun=success_logical)) expect_true(assert_rows(mtcars, rowSums, within_bounds(5,16), cyl, carb, success_fun=success_logical)) expect_true(assert_rows(mnexmpl.data, num_row_NAs, within_bounds(0,2), dplyr::everything(), success_fun=success_logical)) expect_true(assert_rows(nexmpl.data, num_row_NAs, function(x) x < 2, dplyr::everything(), success_fun=success_logical)) expect_true(assert_rows(mtcars, rowSums, function(x) if(x>16) return(FALSE), carb, cyl, success_fun=success_logical)) }) test_that("assert_rows returns correct result if verification passes (w/ `success_append`", { expect_equal( get_assertr_success(assert_rows(mtcars, rowSums, within_bounds(0,2), vs, am, success_fun=success_append)), success_result("assert_rows", "within_bounds(0, 2)", c("vs", "am"), "rowSums", NA)) expect_equal( get_assertr_success(assert_rows(mtcars, num_row_NAs, within_bounds(0,.1), dplyr::everything(), success_fun=success_append)), success_result("assert_rows", "within_bounds(0, 0.1)", colnames(mtcars), "num_row_NAs", NA)) expect_equal( get_assertr_success(assert_rows(mtcars, rowSums, within_bounds(5,16), cyl, carb, success_fun=success_append)), success_result("assert_rows", "within_bounds(5, 16)", c("cyl", "carb"), "rowSums", NA)) expect_equal( get_assertr_success(assert_rows(mnexmpl.data, num_row_NAs, within_bounds(0,2), dplyr::everything(), success_fun=success_append)), success_result("assert_rows", "within_bounds(0, 2)", colnames(mnexmpl.data), "num_row_NAs", NA)) expect_equal( get_assertr_success(assert_rows(nexmpl.data, num_row_NAs, function(x) x < 2, dplyr::everything(), success_fun=success_append)), success_result("assert_rows", "function(x) x < 2", colnames(mnexmpl.data), "num_row_NAs", NA)) expect_equal( get_assertr_success(assert_rows(mtcars, rowSums, function(x) if(x>16) return(FALSE), carb, cyl, success_fun=success_append)), success_result("assert_rows", "function(x) if (x > 16) return(FALSE)", c("carb", "cyl"), "rowSums", NA)) }) test_that("assert_rows performs custom success function if verification passes", { expect_equal(assert_rows(mtcars, rowSums, within_bounds(0,2), vs, am, success_fun=give.validation), "great job!") expect_equal(assert_rows(mtcars, rowSums, within_bounds(5,16), cyl, carb, success_fun=function(x, ...) {return("noice!")}), "noice!") }) test_that("assert_rows raises error if verification fails", { expect_output(assert_rows(mtcars, rowSums, within_bounds(1,2), vs, am, error_fun = just.show.error), "Data frame row reduction 'rowSums' violates predicate 'within_bounds\\(1, 2\\)' 12 times") expect_output(assert_rows(mtcars, num_row_NAs, within_bounds(1,2), dplyr::everything(), error_fun = just.show.error), "Data frame row reduction 'num_row_NAs' violates predicate 'within_bounds\\(1, 2\\)' 32 times") expect_output(assert_rows(mtcars, rowSums, function(x) if(x==10) return(FALSE), carb, cyl, error_fun = just.show.error), "Data frame row reduction 'rowSums' violates predicate 'function\\(x\\) if \\(x == 10\\) return\\(FALSE\\)' 8 times") expect_output(assert_rows(mnexmpl.data, num_row_NAs, within_bounds(0,1), dplyr::everything(), error_fun = just.show.error), "Data frame row reduction 'num_row_NAs' violates predicate 'within_bounds\\(0, 1\\)' 1 time") }) test_that("assert_rows raises *custom error* if verification fails", { expect_error(assert_rows(mnexmpl.data, num_row_NAs, within_bounds(0,1), dplyr::everything(), error_fun=not.helpful), "unspecified error") }) test_that("assert_rows and insist_rows give one column label per assertion", { # 12 rows violate; the two columns used to get one label each, in rotation errs <- assert_rows(mtcars, rowSums, within_bounds(1,2), vs, am, error_fun = error_df_return) expect_equal(unique(errs$column), "vs, am") errs <- assert_rows(mtcars, rowSums, within_bounds(1,2), vs:am, error_fun = error_df_return) expect_equal(unique(errs$column), "vs:am") errs <- insist_rows(mtcars, maha_dist, within_n_mads(1), mpg, cyl, hp, error_fun = error_df_return) expect_equal(unique(errs$column), "mpg, cyl, hp") # 7 rows violate, which two labels could not be recycled over (#83) errs <- assert_rows(mtcars, rowSums, within_bounds(0,1), vs, am, error_fun = error_df_return) expect_equal(nrow(errs), 7) expect_equal(unique(errs$column), "vs, am") }) test_that("assert_rows breaks appropriately", { expect_error(assert_rows(in_set(0,1), mtcars$vs), "argument \"predicate\" is missing, with no default") expect_error(assert_rows(rowSums, in_set(0,1), mtcars$vs), "assert_rows requires columns to be selected. Check number of arguments") expect_error( object = { assert_rows( data = mtcars, row_reduction_fn = rowSums, predicate = in_set(0,1,2), vs, am, tree ) }, regexp = "Column `tree` doesn't exist", class = "error" ) expect_error(assert_rows(mtcars, rowSums, in_set(0,1,2), vs, am, "tree")) expect_error(assert_rows("tree"), "argument \"row_reduction_fn\" is missing, with no default") }) test_that("skip_chain_opts doesn't affect functionality outside chain for assert_rows", { expect_equal(assert_rows(mtcars, rowSums, within_bounds(0,2), vs, am, skip_chain_opts=TRUE), mtcars) expect_equal(assert_rows(mtcars, num_row_NAs, within_bounds(0,.1), dplyr::everything(), skip_chain_opts=TRUE), mtcars) expect_true(assert_rows(mtcars, rowSums, within_bounds(0,2), vs, am, success_fun=success_logical, skip_chain_opts=TRUE)) expect_true(assert_rows(mtcars, num_row_NAs, within_bounds(0,.1), dplyr::everything(), success_fun=success_logical, skip_chain_opts=TRUE)) expect_output(assert_rows(mtcars, rowSums, within_bounds(1,2), vs, am, error_fun=just.show.error, skip_chain_opts=TRUE), "Data frame row reduction 'rowSums' violates predicate 'within_bounds\\(1, 2\\)' 12 times") expect_output(assert_rows(mtcars, num_row_NAs, within_bounds(1,2), dplyr::everything(), error_fun=just.show.error, skip_chain_opts=TRUE), "Data frame row reduction 'num_row_NAs' violates predicate 'within_bounds\\(1, 2\\)' 32 times") }) ###################################### ############### insist ############### test_that("insist returns data if verification passes", { expect_equal(insist(our.iris, within_n_sds(3), Sepal.Length), our.iris) expect_equal(insist(our.iris.3, within_n_sds(2), Sepal.Length), our.iris.3) expect_equal(insist(our.iris, within_n_sds(4), Sepal.Length:Petal.Width), our.iris) }) test_that("insist returns TRUE if verification passes (w/ success_logical)", { expect_true(insist(our.iris, within_n_sds(3), Sepal.Length, success_fun=success_logical)) expect_true(insist(our.iris.3, within_n_sds(2), Sepal.Length, success_fun=success_logical)) expect_true(insist(our.iris, within_n_sds(4), Sepal.Length:Petal.Width, success_fun=success_logical)) }) test_that("insist returns correct result if verification passes (w/ `success_append`", { expect_equal( get_assertr_success(insist(our.iris, within_n_sds(3), Sepal.Length, success_fun=success_append)), success_result("insist", "within_n_sds(3)", "Sepal.Length", NA, NA)) expect_equal( get_assertr_success(insist(our.iris.3, within_n_sds(2), Sepal.Length, success_fun=success_append)), success_result("insist", "within_n_sds(2)", "Sepal.Length", NA, NA)) expect_equal( get_assertr_success(insist(our.iris, within_n_sds(4), Sepal.Length:Petal.Width, success_fun=success_append)), success_result("insist", "within_n_sds(4)", c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"), NA, NA)) }) test_that("insist performs custom success function if verification passes", { expect_equal(insist(our.iris, within_n_sds(3), Sepal.Length, success_fun=give.validation), "great job!") expect_equal(insist(our.iris.3, within_n_sds(2), Sepal.Length, success_fun=function(x, ...){return("noice!")}), "noice!") }) test_that("insist raises error if verification fails", { expect_output(insist(our.iris, within_n_sds(2), Sepal.Length, error_fun = just.show.error), "Column 'Sepal.Length' violates assertion 'within_n_sds\\(2\\)' 6 times") expect_output(insist(our.iris.2, within_n_sds(2), Sepal.Length, error_fun = just.show.error), "Column 'Sepal.Length' violates assertion 'within_n_sds\\(2\\)' 5 times") expect_output(insist(our.iris, within_n_sds(3), Sepal.Length:Petal.Width, error_fun = just.show.error), "Column 'Sepal.Width' violates assertion 'within_n_sds\\(3\\)' 1 time") expect_output(insist(our.iris, within_n_sds(2), Sepal.Length:Petal.Width, error_fun = just.show.error), "Column 'Sepal.Length' violates assertion 'within_n_sds\\(2\\)' 6 times.*Column 'Sepal.Width' violates assertion 'within_n_sds\\(2\\)' 5 times") }) test_that("insist raises *custom error* if verification fails", { expect_error(insist(our.iris, within_n_sds(2), Sepal.Length, error_fun=not.helpful), "unspecified error") expect_error(insist(our.iris.2, within_n_sds(2), Sepal.Length, error_fun=not.helpful), "unspecified error") }) test_that("insist breaks appropriately", { expect_error(insist(within_n_sds(5), mtcars$vs), "insist requires columns to be selected. Check number of arguments") expect_error(insist(mtcars, within_n_sds(5), "vs:am")) expect_error( object = { insist(data = mtcars, predicate_generator = within_n_sds(5), tree) }, regexp = "Column `tree` doesn't exist", class = "error" ) expect_error(insist("tree"), "argument \"predicate_generator\" is missing, with no default") expect_error(insist(iris, within_n_sds(5), Petal.Width:Species), "argument must be a numeric vector") }) test_that("skip_chain_opts doesn't affect functionality outside chain for insist", { expect_equal(insist(our.iris, within_n_sds(3), Sepal.Length, skip_chain_opts=TRUE), our.iris) expect_equal(insist(our.iris.3, within_n_sds(2), Sepal.Length, skip_chain_opts=TRUE), our.iris.3) expect_equal(insist(our.iris, within_n_sds(3), Sepal.Length, success_fun=give.validation, skip_chain_opts=TRUE), "great job!") expect_equal(insist(our.iris.3, within_n_sds(2), Sepal.Length, success_fun=function(x, ...){return("noice!")}, skip_chain_opts=TRUE), "noice!") expect_output(insist(our.iris, within_n_sds(2), Sepal.Length, error_fun=just.show.error, skip_chain_opts=TRUE), "Column 'Sepal.Length' violates assertion 'within_n_sds\\(2\\)' 6 times") expect_output(insist(our.iris.2, within_n_sds(2), Sepal.Length, error_fun=just.show.error, skip_chain_opts=TRUE), "Column 'Sepal.Length' violates assertion 'within_n_sds\\(2\\)' 5 times") }) test_that("insist works with single row data.frames", { single_row_data <- head(mtcars, 1) # a predicate generator that does not need more than one value to work with within.limits <- function(a.vector) within_bounds(10, 30) expect_equal(insist(single_row_data, within.limits, mpg), single_row_data) expect_equal(insist(single_row_data, within.limits, mpg, qsec), single_row_data) expect_equal(insist(single_row_data, within.limits, disp, error_fun = error_logical), FALSE) expect_output(insist(single_row_data, within.limits, disp, error_fun = just.show.error), "Column 'disp' violates assertion 'within.limits' 1 time.*") expect_equal(insist(single_row_data, within.limits, disp, mpg, error_fun = error_logical), FALSE) expect_output(insist(single_row_data, within.limits, disp, mpg, error_fun = just.show.error), "Column 'disp' violates assertion 'within.limits' 1 time.*") # every column that fails is reported expect_output(insist(single_row_data, within.limits, disp, hp, mpg, error_fun = just.show.error), "Column 'hp' violates assertion 'within.limits' 1 time.*") expect_equal(length(attr(insist(single_row_data, within.limits, disp, hp, mpg, error_fun = error_append), "assertr_errors")), 2) expect_equal(length(attr(single_row_data %>% chain_start %>% insist(within.limits, disp, hp, mpg) %>% chain_end(error_fun = error_append), "assertr_errors")), 2) }) ###################################### ############### insist rows ############### test_that("insist_rows returns data if verification passes", { expect_equal(insist_rows(our.iris, maha_dist, within_n_sds(6), dplyr::everything()), our.iris) expect_equal(insist_rows(our.iris, maha_dist, within_n_mads(10), Sepal.Length:Species), our.iris) expect_equal(insist_rows(our.iris, maha_dist, within_n_mads(11), Sepal.Length:Petal.Width), our.iris) }) test_that("insist_rows returns correct result if verification passes (w/ `success_append`", { expect_equal( get_assertr_success(insist_rows(our.iris, maha_dist, within_n_sds(6), dplyr::everything(), success_fun=success_append)), success_result("insist_rows", "within_n_sds(6)", colnames(our.iris), "maha_dist", NA)) expect_equal( get_assertr_success(insist_rows(our.iris, maha_dist, within_n_mads(10), Sepal.Length:Species, success_fun=success_append)), success_result("insist_rows", "within_n_mads(10)", colnames(our.iris), "maha_dist", NA)) expect_equal( get_assertr_success(insist_rows(our.iris, maha_dist, within_n_mads(11), Sepal.Length:Petal.Width, success_fun=success_append)), success_result("insist_rows", "within_n_mads(11)", c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"), "maha_dist", NA)) }) test_that("insist_rows raises error if verification fails", { expect_output(insist_rows(our.iris, maha_dist, within_n_sds(4), dplyr::everything(), error_fun = just.show.error), "Data frame row reduction 'maha_dist' violates predicate 'within_n_sds\\(4\\)' 1 time") expect_output(insist_rows(our.iris, maha_dist, within_n_sds(2), dplyr::everything(), error_fun = just.show.error), "Data frame row reduction 'maha_dist' violates predicate 'within_n_sds\\(2\\)' 8 times") expect_output(insist_rows(our.iris, maha_dist, within_n_mads(5), Sepal.Length:Species, error_fun = just.show.error), "Data frame row reduction 'maha_dist' violates predicate 'within_n_mads\\(5\\)' 1 time") expect_output(insist_rows(our.iris, maha_dist, within_n_mads(5), Sepal.Length:Petal.Width, error_fun = just.show.error), "Data frame row reduction 'maha_dist' violates predicate 'within_n_mads\\(5\\)' 4 times") }) test_that("insist_rows raises *custom error* if verification fails", { expect_error(insist_rows(our.iris, maha_dist, within_n_mads(5), Sepal.Length:Petal.Width, error_fun = not.helpful), "unspecified error") }) test_that("insist_rows breaks appropriately", { expect_error(insist_rows(within_n_sds(5), mtcars$vs), "argument \"predicate_generator\" is missing, with no default") expect_error(insist_rows(mtcars, within_n_sds(10), vs), "object 'vs' not found") expect_error(insist_rows(mtcars, maha_dist, within_n_sds(10), vs), "\"data\" needs to have at least two columns") expect_error(insist_rows(mtcars, maha_dist, within_bound(0, 10), vs, am), "could not find function \"within_bound\"") expect_error(insist_rows(), "argument \"row_reduction_fn\" is missing, with no default") expect_error(insist_rows(mtcars), "argument \"row_reduction_fn\" is missing, with no default") expect_error(insist_rows(mtcars, maha_dist, am, vs), "object 'am' not found") expect_error(insist_rows(mtcars, maha_dist, am, vs, carb), "object 'am' not found") expect_error(insist_rows(lm(Petal.Length ~ Petal.Width, data=iris)), "argument \"row_reduction_fn\" is missing, with no default") }) test_that("skip_chain_opts doesn't affect functionality outside chain for insist_rows", { expect_equal(insist_rows(our.iris, maha_dist, within_n_sds(6), dplyr::everything(), skip_chain_opts=TRUE), our.iris) expect_equal(insist_rows(our.iris, maha_dist, within_n_mads(10), Sepal.Length:Species, skip_chain_opts=TRUE), our.iris) expect_output(insist_rows(our.iris, maha_dist, within_n_sds(4), dplyr::everything(), error_fun=just.show.error, skip_chain_opts=TRUE), "Data frame row reduction 'maha_dist' violates predicate 'within_n_sds\\(4\\)' 1 time") expect_output(insist_rows(our.iris, maha_dist, within_n_sds(2), dplyr::everything(), error_fun=just.show.error, skip_chain_opts=TRUE), "Data frame row reduction 'maha_dist' violates predicate 'within_n_sds\\(2\\)' 8 times") expect_error(insist_rows(within_n_sds(5), mtcars$vs, skip_chain_opts=TRUE), "argument \"predicate_generator\" is missing, with no default") expect_error(insist_rows(mtcars, within_n_sds(10), vs, skip_chain_opts=TRUE), "object 'vs' not found") }) ########################################### ########## chaining works ############ # A special error function for these tests, produces the error but no # standard output. error_no_output <- function (list_of_errors, data=NULL, ...) { stop("assertr stopped execution", call.=FALSE) } strip_attributes <- function(d){ attr(d, "assertr_in_chain_error_fun_override") <- NULL attr(d, "assertr_in_chain_success_fun_override") <- NULL d } ret_num_off_errors <- function(errors, data=NULL, warn=FALSE, ...){ if(!is.null(data) && !is.null(attr(data, "assertr_errors"))) errors <- append(attr(data, "assertr_errors"), errors) num.of.errors <- length(errors) cat(sprintf("There %s %d error%s:\n", ifelse(num.of.errors==1,"is", "are"), num.of.errors, ifelse(num.of.errors==1,"", "s"))) } success_message <- function(data=NULL, ...) { message("Assertion passed") return(data) } error_message <- function(errors, data=NULL) { message("Assertion failed") return(data) } ##### !!! chaining: assert test_that("assert works with chaining", { # only assert with no error code_to_test <- function() { test.df %>% chain_start %>% assert(in_set(0,1,2), x) %>% chain_end %>% strip_attributes } expect_equal(code_to_test(), test.df) # only assert with no error stores success correctly code_to_test <- function() { test.df %>% chain_start(store_success = TRUE) %>% assert(in_set(0,1,2), x) %>% chain_end %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), success_result("assert", "in_set(0, 1, 2)", "x", NA, NA)) # only assert with print state on success in chain code_to_test <- function() { test.df %>% chain_start %>% assert(in_set(0,1,2), x, success_fun=success_message, skip_chain_opts=TRUE) %>% chain_end %>% strip_attributes } expect_message(code_to_test(), "Assertion passed") # only assert with error code_to_test <- function() { test.df %>% chain_start %>% assert(in_set(0,1), x) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # only assert with printed state on error in chain code_to_test <- function() { test.df %>% chain_start %>% assert(in_set(0,1), x, error_fun=error_message, skip_chain_opts=TRUE) %>% chain_end %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # two asserts with no error code_to_test <- function() { test.df2 %>% chain_start %>% assert(in_set(0,1,2), x) %>% assert(within_bounds(1,2),y) %>% chain_end %>% strip_attributes } expect_equal(code_to_test(), test.df2) # two asserts with no error and storing success results code_to_test <- function() { test.df2 %>% chain_start(store_success=TRUE) %>% assert(in_set(0,1,2), x) %>% assert(within_bounds(1,2),y) %>% chain_end %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), append( success_result("assert", "in_set(0, 1, 2)", "x", NA, NA), success_result("assert", "within_bounds(1, 2)", "y", NA, NA) ) ) # only assert with error (1st) code_to_test <- function() { test.df2 %>% chain_start %>% assert(in_set(0,1), x) %>% assert(within_bounds(1,2),y) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # two asserts with error (1st) and chain callback overwriten code_to_test <- function() { test.df2 %>% chain_start %>% assert(in_set(0,1), x, error_fun=error_message, skip_chain_opts=TRUE) %>% assert(within_bounds(1,2),y) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # only assert with error (2st) code_to_test <- function() { test.df2 %>% chain_start %>% assert(within_bounds(1,2),y) %>% assert(in_set(0,1), x) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # only assert with two errors code_to_test <- function() { test.df2 %>% chain_start %>% assert(within_bounds(1,1.5),y) %>% assert(in_set(0,1), x) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There are 2 errors") # two asserts with two errors and one callback overwritten in chain code_to_test <- function() { test.df2 %>% chain_start %>% assert(within_bounds(1,1.5),y, error_fun=error_message, skip_chain_opts=TRUE) %>% assert(in_set(0,1), x) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(expect_message(code_to_test(), "Assertion failed"), "There is 1 error") }) ##### !!! chaining: assert_rows test_that("assert_rows works with chaining", { # only assert_rows with no error code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(col_concat, is_uniq, x, y) %>% chain_end %>% strip_attributes } expect_equal(code_to_test(), test.df2) # only assert_rows with no error and storing success result code_to_test <- function() { test.df2 %>% chain_start(store_success=TRUE) %>% assert_rows(col_concat, is_uniq, x, y) %>% chain_end %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), success_result("assert_rows", "is_uniq", c("x", "y"), "col_concat", NA) ) # only assert_rows with print state on success in chain code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(col_concat, is_uniq, x, y, success_fun=success_message, skip_chain_opts=TRUE) %>% chain_end %>% strip_attributes } expect_message(code_to_test(), "Assertion passed") # only assert_row with error code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(rowSums, not_na, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # only assert_rows with printed state on error in chain code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(rowSums, not_na, x, y, z, error_fun=error_message, skip_chain_opts=TRUE) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # two asserts_row with no error code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(rowSums, is.numeric, x, y, z) %>% assert_rows(col_concat, is.character, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_equal(code_to_test(), test.df2) # two asserts_row with no error ans storing success code_to_test <- function() { test.df2 %>% chain_start(store_success=TRUE) %>% assert_rows(rowSums, is.numeric, x, y, z) %>% assert_rows(col_concat, is.character, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), append( success_result("assert_rows", "is.numeric", c("x", "y", "z"), "rowSums", NA), success_result("assert_rows", "is.character", c("x", "y", "z"), "col_concat", NA) ) ) # only assert_rows with error (1st) code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(rowSums, is.character, x, y, z) %>% assert_rows(col_concat, is.character, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # two assert_rows with error (1st) and callback overwritten in chain code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(rowSums, is.character, x, y, z, error_fun=error_message, skip_chain_opts=TRUE) %>% assert_rows(col_concat, is.character, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # only assert_rows with error (2st) code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(col_concat, is.character, x, y, z) %>% assert_rows(rowSums, is.character, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # only assert_rows with two error code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(col_concat, is.numeric, x, y, z) %>% assert_rows(rowSums, is.character, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There are 2 errors") # only assert_rows with two errors and one callback overwritten in chain code_to_test <- function() { test.df2 %>% chain_start %>% assert_rows(col_concat, is.numeric, x, y, z, error_fun=error_message, skip_chain_opts=TRUE) %>% assert_rows(rowSums, is.character, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(expect_message(code_to_test(), "Assertion failed")) }) ##### !!! chaining: insist test_that("insist works with chaining", { # only insist with no error code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_mads(5), x, y, z) %>% chain_end %>% strip_attributes } expect_equal(code_to_test(), test.df2) # only insist with no error ans storing success code_to_test <- function() { test.df2 %>% chain_start(store_success=TRUE) %>% insist(within_n_mads(5), x, y, z) %>% chain_end %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), success_result("insist", "within_n_mads(5)", c("x", "y", "z"), NA, NA) ) # only insist with print state on success in chain code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_mads(5), x, y, z, success_fun=success_message, skip_chain_opts=TRUE) %>% chain_end %>% strip_attributes } expect_message(code_to_test(), "Assertion passed") # only insist with error (3 of them, though) code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_mads(.4), x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There are 3 errors") # only insist with printed state on error in chain code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_mads(.4), x, y, z, error_fun=error_message, skip_chain_opts=TRUE) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # two insists with no error code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_mads(5), x, y, z) %>% insist(within_n_sds(5), x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_equal(code_to_test(), test.df2) # two insists with no error and storing success code_to_test <- function() { test.df2 %>% chain_start(store_success=TRUE) %>% insist(within_n_mads(5), x, y, z) %>% insist(within_n_sds(5), x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), append( success_result("insist", "within_n_mads(5)", c("x", "y", "z"), NA, NA), success_result("insist", "within_n_sds(5)", c("x", "y", "z"), NA, NA) ) ) # two insists with error (1st) code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_mads(.4), x, y, z) %>% insist(within_n_sds(5), x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There are 3 errors") # two insists with error (1st) and callback overwritten in chain code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_mads(.4), x, y, z, error_fun=error_message, skip_chain_opts=TRUE) %>% insist(within_n_sds(5), x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # two insists with error (2st) code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_sds(5), x, y, z) %>% insist(within_n_mads(.4), x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There are 3 errors") # two insists with two error code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_sds(.4), x, y, z) %>% insist(within_n_mads(.4), x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There are 6 errors") # two insists with two errors and one callback overwritten in chain code_to_test <- function() { test.df2 %>% chain_start %>% insist(within_n_sds(.4), x, y, z, error_fun=error_message, skip_chain_opts=TRUE) %>% insist(within_n_mads(.4), x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(expect_message(code_to_test(), "Assertion failed")) }) ##### !!! chaining: insist_rows test_that("insist_rows works with chaining", { # only insist_rows with no error code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(maha_dist, function(x){function(...) TRUE}, x, y, z) %>% chain_end %>% strip_attributes } expect_equal(code_to_test(), test.df2) # only insist_rows with no error and storing success code_to_test <- function() { test.df2 %>% chain_start(store_success=TRUE) %>% insist_rows(maha_dist, function(x){function(...) TRUE}, x, y, z) %>% chain_end %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), success_result("insist_rows", as.character(expression(function(x){function(...) TRUE})), c("x", "y", "z"), "maha_dist", NA) ) # only insist_rows with print state on success in chain code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(maha_dist, function(x){function(...) TRUE}, x, y, z, success_fun=success_message, skip_chain_opts=TRUE) %>% chain_end %>% strip_attributes } expect_message(code_to_test(), "Assertion passed") # only insist_rows with error (3 of them, though) code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(maha_dist, function(x){function(...) FALSE}, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # only insist_rows with printed state on error in chain code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(maha_dist, function(x){function(...) FALSE}, x, y, z, error_fun=error_message, skip_chain_opts=TRUE) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # two insists_rows with no error code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(maha_dist, function(x){function(...) TRUE}, x, y, z) %>% insist_rows(col_concat, function(x){function(...) TRUE}, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_equal(code_to_test(), test.df2) # two insists_rows with no error and storing success results code_to_test <- function() { test.df2 %>% chain_start(store_success=TRUE) %>% insist_rows(maha_dist, function(x){function(...) TRUE}, x, y, z) %>% insist_rows(col_concat, function(x){function(...) TRUE}, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), append( success_result("insist_rows", as.character(expression(function(x){function(...) TRUE})), c("x", "y", "z"), "maha_dist", NA), success_result("insist_rows", as.character(expression(function(x){function(...) TRUE})), c("x", "y", "z"), "col_concat", NA) ) ) # two insists_rows with error (1st) code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(maha_dist, function(x){function(...) FALSE}, x, y, z) %>% insist_rows(col_concat, function(x){function(...) TRUE}, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # two insists_rows with error (1st) and callback overwritten in chain code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(maha_dist, function(x){function(...) FALSE}, x, y, z, error_fun=error_message, skip_chain_opts=TRUE) %>% insist_rows(col_concat, function(x){function(...) TRUE}, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # two insists with error (2st) code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(col_concat, function(x){function(...) TRUE}, x, y, z) %>% insist_rows(maha_dist, function(x){function(...) FALSE}, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # two insists_rows with two errors code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(col_concat, function(x){function(...) FALSE}, x, y, z) %>% insist_rows(maha_dist, function(x){function(...) FALSE}, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There are 2 errors") # two insists_rows with two errors and one callback overwritten in chain code_to_test <- function() { test.df2 %>% chain_start %>% insist_rows(col_concat, function(x){function(...) FALSE}, x, y, z, error_fun=error_message, skip_chain_opts=TRUE) %>% insist_rows(maha_dist, function(x){function(...) FALSE}, x, y, z) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(expect_message(code_to_test(), "Assertion failed"), "There is 1 error") }) ##### !!! chaining: verify test_that("verify works with chaining", { # only verify with no error code_to_test <- function() { test.df2 %>% chain_start %>% verify(x >= 0) %>% chain_end %>% strip_attributes } expect_equal(code_to_test(), test.df2) # only verify with no error ans storing success results code_to_test <- function() { test.df2 %>% chain_start(store_success=TRUE) %>% verify(x >= 0) %>% chain_end %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), success_result("verify", "x >= 0", NA, NA, NA) ) # only verify with print state on success in chain code_to_test <- function() { test.df2 %>% chain_start %>% verify(x >= 0, success_fun=success_message, skip_chain_opts=TRUE) %>% chain_end %>% strip_attributes } expect_message(code_to_test(), "Assertion passed") # only verify with error code_to_test <- function() { test.df2 %>% chain_start %>% verify(x > 0) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # only verify with printed state on error in chain code_to_test <- function() { test.df2 %>% chain_start %>% verify(x > 0, error_fun=error_message, skip_chain_opts=TRUE) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # two verify with no error code_to_test <- function() { test.df2 %>% chain_start %>% verify(x >= 0) %>% verify(y > 0) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_equal(code_to_test(), test.df2) # two verify with no error and storing success results code_to_test <- function() { test.df2 %>% chain_start(store_success=TRUE) %>% verify(x >= 0) %>% verify(y > 0) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_equal( get_assertr_success(code_to_test()), append( success_result("verify", "x >= 0", NA, NA, NA), success_result("verify", "y > 0", NA, NA, NA) ) ) # two verify with error (1st) code_to_test <- function() { test.df2 %>% chain_start %>% verify(x > 0) %>% verify(y > 0) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # two verify with error (1st) and callback overwritten in chain code_to_test <- function() { test.df2 %>% chain_start %>% verify(x > 0, error_fun=error_message, skip_chain_opts=TRUE) %>% verify(y > 0) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_message(code_to_test(), "Assertion failed") # two verify with error (2st) code_to_test <- function() { test.df2 %>% chain_start %>% verify(y > 0) %>% verify(x > 0) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There is 1 error") # two verify with two errors code_to_test <- function() { test.df2 %>% chain_start %>% verify(y > 2) %>% verify(x > 0) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(code_to_test(), "There are 2 errors") # two verify with two errors and one callback overwritten in chain code_to_test <- function() { test.df2 %>% chain_start %>% verify(y > 2, error_fun=error_message, skip_chain_opts=TRUE) %>% verify(x > 0) %>% chain_end(error_fun=ret_num_off_errors) %>% strip_attributes } expect_output(expect_message(code_to_test(), "Assertion failed"), "There is 1 error") }) test_that("chain_end leaves no chain state on the data (#115)", { df <- data.frame(X1=letters, X2=seq(1,26), stringsAsFactors=FALSE) hand.back <- function(errors, data=NULL, ...) data # the example from the issue chained <- df %>% chain_start %>% assert(is_uniq, X1, X2) %>% assert(is.character, X1) %>% assert(is.numeric, X2) %>% chain_end expect_equal(chained, df) # a success_fun given to a later assertion is used again expect_true(verify(chained, X2 > 0, success_fun=success_logical)) # after a chain whose errors were handed back with the data warned <- df %>% chain_start %>% assert(within_bounds(0,5), X2) %>% chain_end(error_fun=hand.back) expect_equal(warned, df) # a failed obligatory rule no longer makes later assertions get skipped flagged <- df %>% chain_start %>% verify(X2 > 100, obligatory=TRUE) %>% chain_end(error_fun=hand.back) expect_equal(flagged, df) expect_equal(verify(flagged, X2 > 100, error_fun=error_logical), FALSE) # errors that the caller asked to keep are still attached kept <- df %>% chain_start %>% assert(within_bounds(0,5), X2) %>% chain_end(error_fun=error_append) expect_equal(length(attr(kept, "assertr_errors")), 1) }) test_that("error_report counts an assertion on several columns as one verb", { two.bad <- data.frame(a=c(1, 20), b=c(1, 30), c=c(1, 2)) # one failing column: one error, one verb expect_output(suppressWarnings(assert(two.bad, within_bounds(0,10), a, error_fun=warn_report)), "There is 1 error across 1 verb:", fixed = TRUE) # two failing columns in one assertion are still one verb expect_output(suppressWarnings(assert(two.bad, within_bounds(0,10), a, b, c, error_fun=warn_report)), "There are 2 errors across 1 verb:", fixed = TRUE) expect_output(suppressWarnings(insist(two.bad, function(a.vector) within_bounds(0,10), a, b, error_fun=warn_report)), "There are 2 errors across 1 verb:", fixed = TRUE) expect_output(expect_error(assert(two.bad, within_bounds(0,10), a, b, error_fun=error_report), "assertr stopped execution"), "There are 2 errors across 1 verb:", fixed = TRUE) # in a chain, each assertion counts once expect_output(suppressWarnings(two.bad %>% chain_start %>% assert(within_bounds(0,10), a, b) %>% verify(a < 10) %>% chain_end(error_fun=warn_report)), "There are 3 errors across 2 verbs:", fixed = TRUE) # also when the same assertion is written twice expect_output(suppressWarnings(two.bad %>% chain_start %>% assert(within_bounds(0,10), a, b) %>% assert(within_bounds(0,10), a, b) %>% chain_end(error_fun=warn_report)), "There are 4 errors across 2 verbs:", fixed = TRUE) }) test_that("warning_append marks every error it attaches as a warning", { two.bad <- data.frame(a=c(1, 20), b=c(1, 30), c=c(1, 2)) marked <- function(data) vapply(attr(data, "assertr_errors"), function(x) isTRUE(attr(x, "warning")), logical(1)) # one failing column, or a verb that gives a single error expect_equal(marked(assert(two.bad, within_bounds(0,10), a, error_fun=warning_append)), TRUE) expect_equal(marked(verify(two.bad, a < 10, error_fun=warning_append)), TRUE) # an assertion that fails on two columns attaches two errors, both marked expect_equal(marked(assert(two.bad, within_bounds(0,10), a, b, c, error_fun=warning_append)), c(TRUE, TRUE)) expect_equal(marked(insist(two.bad, function(a.vector) within_bounds(0,10), a, b, error_fun=warning_append)), c(TRUE, TRUE)) # errors that were already on the data are left as they were expect_equal(marked(two.bad %>% assert(within_bounds(0,10), a, error_fun=error_append) %>% assert(within_bounds(0,10), a, b, error_fun=warning_append)), c(FALSE, TRUE, TRUE)) # error_append marks nothing expect_equal(marked(assert(two.bad, within_bounds(0,10), a, b, error_fun=error_append)), c(FALSE, FALSE)) # inside a chain expect_equal(marked(two.bad %>% chain_start %>% assert(within_bounds(0,10), a, b, error_fun=warning_append, skip_chain_opts=TRUE) %>% chain_end(error_fun=error_append)), c(TRUE, TRUE)) }) test_that("a failing assertion leaves the random number generator as it was", { two.bad <- data.frame(a=c(1, 20), b=c(1, 30)) within.limits <- function(a.vector) within_bounds(0, 10) invisible(runif(1)) # so that the generator has a state to look at rng.state <- function() get(".Random.seed", envir=globalenv()) # `code` is only run once the state before it has been noted rng.moved <- function(code){ before <- rng.state(); code; !identical(rng.state(), before) } expect_false(rng.moved(assert(two.bad, within_bounds(0,100), a, b))) expect_false(rng.moved(verify(two.bad, a < 10, error_fun=error_append))) expect_false(rng.moved(assert(two.bad, within_bounds(0,10), a, b, error_fun=error_append))) expect_false(rng.moved(insist(two.bad, within.limits, a, b, error_fun=error_append))) expect_false(rng.moved(assert_rows(two.bad, rowSums, within_bounds(0,10), a, b, error_fun=error_append))) expect_false(rng.moved(insist_rows(two.bad, rowSums, within.limits, a, b, error_fun=error_append))) }) test_that("errors from one assertion share an id, and each assertion has its own", { two.bad <- data.frame(a=c(1, 20), b=c(1, 30)) ids <- function(data) vapply(attr(data, "assertr_errors"), function(x) x$assertion.id, character(1)) checked <- two.bad %>% assert(within_bounds(0,10), a, b, error_fun=error_append) %>% verify(a < 10, error_fun=error_append) %>% verify(b < 10, error_fun=error_append) expect_equal(length(ids(checked)), 4) expect_equal(ids(checked)[1], ids(checked)[2]) expect_equal(length(unique(ids(checked))), 3) # ids start with a letter and have only letters and digits, so that they # can be used as identifiers elsewhere (as the id of an HTML element, say) expect_true(all(grepl("^[A-Za-z][A-Za-z0-9]*$", ids(checked)))) # ids do not depend on the random number generator: they differ even when # it is put back in the same state before each assertion invisible(runif(1)) seed <- get(".Random.seed", envir=globalenv()) same.state.ids <- vapply(1:20, function(i){ assign(".Random.seed", seed, envir=globalenv()) ids(verify(two.bad, a < 10, error_fun=error_append)) }, character(1)) expect_equal(length(unique(same.state.ids)), 20) }) ################################### ##### !!! rlang .data and unquoting test_that("all assertions work with .data pronoun without chains", { # Define some data we might accidentally reference outside the test.df frame y <- 0:2 ## verify() ## # Cases where the name exists: # Also test the logical versions here to make sure nothing too weird is happening. expect_equal(verify(test.df, .data$x <= 2), test.df) # expect success expect_true(verify(test.df, .data$x <= 2, success_fun = success_logical)) expect_output(verify(test.df, .data$x > 2, error_fun = just.show.error), "verification [.data$x > 2] failed! (3 failures)", fixed = TRUE) expect_false(verify(test.df, .data$x > 2, error_fun = error_logical)) # Cases where the name doesn't exist: expect_error(verify(test.df, .data$y <= 2, error_fun = just.show.error)) # expect success from y defined above expect_equal(verify(test.df, y <= 2), test.df) ## assert() ## expect_equal(assert(test.df, within_bounds(-Inf, 2), x), test.df) expect_output( expect_error(assert(test.df, within_bounds(2, Inf), x)), regexp="Column 'x' violates assertion 'within_bounds(2, Inf)' 2 times", fixed=TRUE ) ## insist() ## expect_equal(insist(test.df, within_n_sds(1), x), test.df) expect_output(insist(test.df, within_n_sds(0.1), x, error_fun = just.show.error), "Column 'x' violates assertion 'within_n_sds(0.1)' 2 times", fixed = TRUE) }) test_that("all assertions work with .data pronoun in chains", { # Define some data we might accidentally reference outside the test.df frame y <- 0:2 ## verify() ## # Cases where the name exists: # Also test the logical versions here to make sure nothing too weird is happening. expect_equal(test.df %>% verify(x <= 2), test.df) expect_true(test.df %>% verify(x <= 2, success_fun = success_logical)) expect_output(test.df %>% verify(x > 2, error_fun = just.show.error), "verification [x > 2] failed! (3 failures)", fixed = TRUE) expect_false(test.df %>% verify(x > 2, error_fun = error_logical)) # Cases where the name doesn't exist: #expect_error(test.df %>% verify(y <= 2, error_fun = just.show.error)) expect_error(test.df %>% verify(.data$y <= 2, error_fun = just.show.error)) expect_equal(test.df %>% verify(y <= 2), test.df) ## assert() ## expect_equal(test.df %>% assert(within_bounds(-Inf, 2), x), test.df) expect_output(test.df %>% assert(within_bounds(2, Inf), x, error_fun = just.show.error), "Column 'x' violates assertion 'within_bounds(2, Inf)' 2 times", fixed = TRUE) ## insist() ## expect_equal(test.df %>% insist(within_n_sds(1), x), test.df) expect_output(test.df %>% insist(within_n_sds(0.1), x, error_fun = just.show.error), "Column 'x' violates assertion 'within_n_sds(0.1)' 2 times", fixed = TRUE) }) test_that("all assertions work with !! unquoting", { x <- 2:4 y <- 0:2 z <- 3 varname <- rlang::quo(x) ## verify() ## expect_equal(verify(test.df, !! x > 1), test.df) # 2:4 > 1 expect_equal(verify(test.df, !! x > .data$x), test.df) # 2:4 > .data$x expect_equal(verify(test.df, !! y == .data$x), test.df) # 0:2 == .data$x expect_equal(verify(test.df, !! varname < 3), test.df) # x < 3 expect_output(verify(test.df, !! x < 1, error_fun = just.show.error), "verification [2:4 < 1] failed! (3 failures)", fixed = TRUE) expect_output(verify(test.df, !! x < x, error_fun = just.show.error), "verification [2:4 < x] failed! (3 failures)", fixed = TRUE) expect_output(verify(test.df, !! y != x, error_fun = just.show.error), "verification [0:2 != x] failed! (3 failures)", fixed = TRUE) expect_output(verify(test.df, !! varname > 3, error_fun = just.show.error), # this is a weird error message, but it's fine I guess "verification [(~x) > 3] failed! (3 failures)", fixed = TRUE) ## assert() ## # Note that !!min(x) becomes min(2:4), so this works: expect_equal(assert(test.df, within_bounds(-Inf, !!min(x)), x), test.df) expect_equal(assert(test.df, within_bounds(-Inf, 2), !! varname), test.df) expect_output(assert(test.df, within_bounds(2, Inf), !! varname, error_fun = just.show.error), "Column 'x' violates assertion 'within_bounds(2, Inf)' 2 times", fixed = TRUE) expect_output(assert(test.df, within_bounds(!!z-1, Inf), x, error_fun = just.show.error), "Column 'x' violates assertion 'within_bounds(3 - 1, Inf)' 2 times", fixed = TRUE) ## insist() ## expect_equal(test.df %>% insist(within_n_sds(!! z), !! varname), test.df) expect_output(test.df %>% insist(within_n_sds(!! z/10), !! varname, error_fun = just.show.error), "Column 'x' violates assertion 'within_n_sds(3/10)' 2 times", fixed = TRUE) }) test_that("verify works with variable-argument-length is_uniq", { # These x, y, z should not be used by the is_uniq below because the # predicates use a data mask x <- 2:4 y <- 0:2 z <- 3 varname <- rlang::quo(x) # test.df2 <- data.frame(x = c(0, 1, 2), # y = c(2, 1.5, 1), # z = c(0,NA, -1)) expect_equal(verify(test.df2, is_uniq(x)), test.df2) expect_equal(verify(test.df2, is_uniq(x, y)), test.df2) expect_equal(verify(test.df2, is_uniq(x, y, z, allow.na=TRUE)), test.df2) expect_equal(verify(test.df2, is_uniq(!!varname)), test.df2) df_dups <- data.frame(x = c(0, 0, 1, 2), y = c(1, 2, 2, NA), z = c(1, 1, 2, 3)) expect_output(verify(df_dups, is_uniq(x, z), error_fun = just.show.error), "verification [is_uniq(x, z)] failed! (2 failures)", fixed = TRUE) expect_equal(verify(df_dups, is_uniq(x, y, allow.na = TRUE)), df_dups) expect_output(verify(df_dups, is_uniq(x, y), error_fun = just.show.error), "verification [is_uniq(x, y)] failed! (1 failure)", fixed = TRUE) }) test_that("description is correctly stored and displayed in results", { description <- "vs and am should be only 0 or 1." # Error check_error <- mtcars %>% assert(in_set(0, 2), am, vs, error_fun = error_return, description=description) # error outside chain expect_equal( check_error[[1]][["description"]], description ) expect_output( print(check_error[[1]]), description ) # error inside chain check_error <- mtcars %>% chain_start %>% assert(in_set(0, 2), am, vs, description=description) %>% chain_end(error_fun = error_return) expect_equal( check_error[[1]][["description"]], description ) expect_output( print(check_error[[1]]), description ) # Success check_success_df <- function() { mtcars %>% assert(in_set(0, 1), am, vs, success_fun=success_df_return, description=description) } check_success_report <- function() { mtcars %>% assert(in_set(0, 1), am, vs, success_fun=success_report, description=description) } # success outside chain expect_equal( check_success_df()[1, "description"], description ) expect_output( print(check_success_report()), description ) # success inside chain check_success_df <- function() { mtcars %>% chain_start(store_success=TRUE) %>% assert(in_set(0, 1), am, vs, description=description) %>% chain_end(success_fun=success_df_return) } check_success_report <- function() { mtcars %>% chain_start(store_success=TRUE) %>% assert(in_set(0, 1), am, vs, success_fun=success_report, description=description) %>% chain_end(success_fun=success_df_return) } expect_equal( check_success_df()[1, "description"], description ) expect_output( print(check_success_report()), description ) # Defect check_defect_df <- function() { mtcars %>% dplyr::select(-am) %>% verify(has_all_names("am", "vs"), obligatory=TRUE, error_fun=error_append) %>% assert(in_set(0, 1), am, vs, defect_fun=defect_df_return, description=description) } check_defect_report <- function() { mtcars %>% dplyr::select(-am) %>% verify(has_all_names("am", "vs"), obligatory=TRUE, error_fun=error_append) %>% assert(in_set(0, 1), am, vs, defect_fun=defect_report, description=description) } # defect outside chain expect_equal( check_defect_df()[1, "description"], description ) expect_output( print(check_defect_report()), description ) # defect inside chain check_defect_df <- function() { mtcars %>% select(-am) %>% chain_start %>% verify(has_all_names("am", "vs"), obligatory=TRUE) %>% assert(in_set(0, 1), am, vs, description=description) %>% chain_end(defect_fun=defect_df_return) } check_defect_report <- function() { mtcars %>% select(-am) %>% chain_start %>% verify(has_all_names("am", "vs"), obligatory=TRUE) %>% assert(in_set(0, 1), am, vs, defect_fun=defect_report, description=description) %>% chain_end(defect_fun=defect_df_return) } expect_equal( check_success_df()[1, "description"], description ) expect_output( print(check_success_report()), description ) }) test_that("assert passes on zero-row data frames (#95)", { a_tibble <- tibble::tibble( a = c(0, 0), b = c(0,0) ) %>% head( n = 0) expect_silent({ assert(data = a_tibble, predicate = function(x) nrow(x) == 0L, dplyr::everything()) }) expect_equal(assert(a_tibble, not_na, a, b), a_tibble) expect_equal(assert(a_tibble, within_bounds(0,1), a), a_tibble) }) test_that("insist passes on zero-row data frames", { no.rows <- mtcars[0, ] expect_equal(insist(no.rows, within_n_sds(3), mpg, hp), no.rows) expect_equal(insist(no.rows, within_n_mads(3), mpg), no.rows) # also with a predicate generator that is not one of ours expect_equal(insist(no.rows, function(a.vector) within_bounds(10, 30), mpg, hp), no.rows) expect_true(insist(no.rows, within_n_sds(3), mpg, success_fun=success_logical)) # and it does not end a chain expect_equal(no.rows %>% chain_start %>% insist(within_n_sds(3), mpg) %>% chain_end, no.rows) }) test_that("assert_rows passes on zero-row data frames", { no.rows <- mtcars[0, ] expect_equal(assert_rows(no.rows, num_row_NAs, within_bounds(0,1), mpg, hp), no.rows) expect_equal(assert_rows(no.rows, col_concat, is_uniq, mpg, hp), no.rows) # also with a row reduction function that cannot work without rows expect_equal(assert_rows(no.rows, maha_dist, within_bounds(0,10), mpg, hp), no.rows) expect_true(assert_rows(no.rows, maha_dist, within_bounds(0,10), mpg, hp, success_fun=success_logical)) }) test_that("insist_rows passes on zero-row data frames", { no.rows <- mtcars[0, ] expect_equal(insist_rows(no.rows, maha_dist, within_n_mads(3), mpg, hp), no.rows) expect_equal(insist_rows(no.rows, num_row_NAs, within_n_sds(3), mpg, hp), no.rows) expect_true(insist_rows(no.rows, maha_dist, within_n_mads(3), mpg, hp, success_fun=success_logical)) # and it does not end a chain expect_equal(no.rows %>% chain_start %>% insist_rows(maha_dist, within_n_mads(3), mpg, hp) %>% chain_end, no.rows) }) test_that("assertions warn when the column selection matches no columns (#113)", { # these used to pass without a word expect_warning(assert(mtcars, function(x) FALSE, dplyr::starts_with("zzz")), "assert: the selection 'dplyr::starts_with(\"zzz\")' matched no columns, so nothing was checked", fixed = TRUE) expect_warning(insist(mtcars, within_n_sds(1), dplyr::starts_with("zzz")), "insist: the selection 'dplyr::starts_with(\"zzz\")' matched no columns, so nothing was checked", fixed = TRUE) expect_warning(assert_rows(mtcars, num_row_NAs, within_bounds(0,1), dplyr::starts_with("zzz")), "assert_rows: the selection 'dplyr::starts_with(\"zzz\")' matched no columns, so nothing was checked", fixed = TRUE) # the data still comes back, and a success_fun is still used expect_equal(suppressWarnings(assert(mtcars, function(x) FALSE, dplyr::starts_with("zzz"))), mtcars) expect_equal(suppressWarnings(insist(mtcars, within_n_sds(1), dplyr::starts_with("zzz"))), mtcars) expect_true(suppressWarnings(assert(mtcars, not_na, dplyr::starts_with("zzz"), success_fun=success_logical))) # no warning when columns are selected, whether or not there are rows expect_silent(assert(mtcars, not_na, dplyr::starts_with("m"))) expect_silent(assert(mtcars[0, ], not_na, mpg)) # the row reduction function is not called when there are no columns to reduce expect_equal(suppressWarnings(assert_rows(mtcars, col_concat, is_uniq, dplyr::starts_with("zzz"), error_fun=error_logical)), mtcars) expect_equal(suppressWarnings(assert_rows(mtcars, maha_dist, within_bounds(0,1), dplyr::starts_with("zzz"))), mtcars) expect_warning(insist_rows(mtcars, maha_dist, within_n_mads(3), dplyr::starts_with("zzz")), "insist_rows: the selection 'dplyr::starts_with(\"zzz\")' matched no columns, so nothing was checked", fixed = TRUE) expect_equal(suppressWarnings(insist_rows(mtcars, num_row_NAs, within_n_sds(3), dplyr::starts_with("zzz"))), mtcars) }) test_that("errors for a missing column selection say what to do instead", { expect_error(insist(mtcars, within_n_sds(3)), "insist requires columns to be selected. Check number of arguments", fixed = TRUE) expect_error(assert(mtcars, not_na), "assert requires columns to be selected. Check number of arguments. To check a condition on the whole data frame, use verify", fixed = TRUE) expect_error(assert_rows(mtcars, num_row_NAs, within_bounds(0,1)), "assert_rows requires columns to be selected. Check number of arguments. Select all columns with everything()", fixed = TRUE) expect_error(insist_rows(mtcars, maha_dist, within_n_mads(3)), "insist_rows requires columns to be selected. Check number of arguments. Select all columns with everything()", fixed = TRUE) })