[med-svn] [r-cran-testit] 01/05: New upstream version 0.7

Andreas Tille tille at debian.org
Fri Sep 29 14:59:47 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository r-cran-testit.

commit 4967673da3a6d25210921f93070e092b2914d158
Author: Andreas Tille <tille at debian.org>
Date:   Fri Sep 29 16:56:51 2017 +0200

    New upstream version 0.7
---
 DESCRIPTION                |  10 ++---
 MD5                        |  18 ++++----
 NAMESPACE                  |   2 +
 NEWS                       |   8 ++++
 R/testit.R                 | 102 +++++++++++++++++++++++++++++++++++----------
 README.md                  |   9 +++-
 man/assert.Rd              |  63 ++++++++++++++++++++++------
 man/has_message.Rd         |   3 +-
 man/test_pkg.Rd            |   1 +
 tests/testit/test-assert.R |  15 ++++++-
 10 files changed, 177 insertions(+), 54 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
index c17949e..c20e284 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,8 +1,8 @@
 Package: testit
 Type: Package
 Title: A Simple Package for Testing R Packages
-Version: 0.6
-Date: 2016-11-09
+Version: 0.7
+Date: 2017-05-21
 Author: Yihui Xie
 Maintainer: Yihui Xie <xie at yihui.name>
 Description: Provides two convenience functions assert() and test_pkg() to
@@ -12,8 +12,8 @@ URL: https://github.com/yihui/testit
 BugReports: https://github.com/yihui/testit/issues
 Suggests: rstudioapi
 Collate: 'testit.R' 'utils.R'
-RoxygenNote: 5.0.1
+RoxygenNote: 6.0.1
 NeedsCompilation: no
-Packaged: 2016-11-08 21:51:20 UTC; yihui
+Packaged: 2017-05-21 04:53:18 UTC; yihui
 Repository: CRAN
-Date/Publication: 2016-11-09 18:28:59
+Date/Publication: 2017-05-22 05:16:36 UTC
diff --git a/MD5 b/MD5
index e55b45f..5db1d8d 100644
--- a/MD5
+++ b/MD5
@@ -1,14 +1,14 @@
-c210b4a01bde165c812cfcef436a8b65 *DESCRIPTION
-2a706e1aaf23d48acdbbc7ff8ff87005 *NAMESPACE
-ea78f195a2427276a1cbda53c65d2313 *NEWS
-1169a417364bc75090bac943082be032 *R/testit.R
+e1d4b01eadefdc02dc579ca7d452251f *DESCRIPTION
+8d4dda1a84a55725a51b9963e3ee588d *NAMESPACE
+e162e8f5079d136a7bcd23162fdf00cc *NEWS
+ef28927bca5eda6466a47c8619f52985 *R/testit.R
 c24fd4cbad5d330a945a9e04cd75822b *R/utils.R
-7d92568615093174e38db7bd80452db8 *README.md
+d7abed7e95e250b294874a94e4e02255 *README.md
 4aae9b69bfa4f9baa95bd50f98274ba3 *inst/rstudio/addins.dcf
-d39845785bc048cefcec31007bcd918a *man/assert.Rd
-7e8dd84fd84aa824305aeec560ef65a6 *man/has_message.Rd
-32621e7874660ff8c5eb228102bb2a93 *man/test_pkg.Rd
+f5601995b089ef6ab109ba1bedae2456 *man/assert.Rd
+4811220ddf9663cc8e21554be5dafcad *man/has_message.Rd
+4e059d0078876de01046e14a5a0a13ba *man/test_pkg.Rd
 fc95de596ff143707ce5da2874086a92 *tests/test-all.R
 5330c047ff926dcaf08d9266db9a71f8 *tests/test-error/test-error.R
-0910ad4200cb30bee30cd73ab59fe63b *tests/testit/test-assert.R
+80027fdc69c299a33a6b22e37f0e1055 *tests/testit/test-assert.R
 e058e991696d0946fdf35e115fbf3dc0 *tests/testit/test-utils.R
diff --git a/NAMESPACE b/NAMESPACE
index ef4f56b..5f39ad7 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,3 +1,5 @@
+# Generated by roxygen2: do not edit by hand
+
 export("%==%")
 export(assert)
 export(has_error)
diff --git a/NEWS b/NEWS
index 70f29aa..b7cd214 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+    CHANGES IN testit VERSION 0.7 (unreleased)
+
+NEW FEATURES
+
+  o provided an alternative way to write assertions of the form
+  assert('fact', {(condition_2); (condition_2)}); see ?testit::assert for more
+  information
+
     CHANGES IN testit VERSION 0.6
 
 NEW FEATURES
diff --git a/R/testit.R b/R/testit.R
index db33974..b81eccd 100644
--- a/R/testit.R
+++ b/R/testit.R
@@ -1,29 +1,48 @@
-#' Assertions with a message
+#' Assertions with an optional message
 #'
-#' The function \code{assert()} was built from \code{\link{stopifnot}()}. It
+#' The function \code{assert()} was inspired by \code{\link{stopifnot}()}. It
 #' emits a message in case of errors, which can be a helpful hint for diagnosing
 #' the errors (\code{stopifnot()} only prints the possibly truncated source code
 #' of the expressions).
+#'
+#' There are two ways to write R expressions in the \code{...} argument.
+#'
+#' The first way is a series of R expressions (each expression is passed as an
+#' individual argument) that return vectors of \code{TRUE}'s (if \code{FALSE} is
+#' returned anywhere, an error will show up).
+#'
+#' The second way is a single R expression wrapped in \code{{}} and passed as a
+#' single argument. This expression may contain multiple sub-expressions. A
+#' sub-expression is treated as a test condition if it is wrapped in \code{()}
+#' (meaning its value will be checked to see if it is a logical vector
+#' containing any \code{FALSE} values) , otherwise it is evaluated in the normal
+#' way and its value will not be checked. If the value of the last
+#' sub-expression is logical, it will also be treated as a test condition.
 #' @param fact a message for the assertions when any of them fails; treated the
 #'   same way as expressions in \code{...} if it is not a character string,
 #'   which means you do not have to provide a message to this function
-#' @param ... any number of R expressions, presumably to return vectors of
-#'   \code{TRUE}'s (if \code{FALSE} is returned anywhere, an error will show up)
+#' @param ... any number of R expressions; see Details
 #' @return Invisible \code{NULL} if all expressions returned \code{TRUE},
 #'   otherwise an error is signalled and the user-provided message is emitted.
-#' @note The internal implementation of \code{stopifnot()} is different with the
-#'   function in R \pkg{base}: (1) the custom message \code{fact} is emitted if
-#'   an error occurs (2) \code{assert()} requires the logical values to be
-#'   non-empty (3) if \code{...} contains a compound expression in \code{{}}
-#'   which returns \code{FALSE} (e.g., \code{if (TRUE) {1+1; FALSE}}), the first
-#'   and the last but one line of the source code from \code{\link{deparse}()}
-#'   are printed in the error message, otherwise the first line is printed
+#' @note The internal implementation of \code{assert()} is different with the
+#'   \code{stopifnot()} function in R \pkg{base}: (1) the custom message
+#'   \code{fact} is emitted if an error occurs; (2) \code{assert()} requires the
+#'   logical values to be non-empty (\code{logical(0)} will trigger an error);
+#'   (3) if \code{...} contains a compound expression in \code{{}} that returns
+#'   \code{FALSE} (e.g., \code{if (TRUE) {1+1; FALSE}}), the first and the last
+#'   but one line of the source code from \code{\link{deparse}()} are printed in
+#'   the error message, otherwise the first line is printed; (4) the arguments
+#'   in \code{...} are evaluated sequentially, and \code{assert()} will signal
+#'   an error upon the first failed assertion, and will ignore the rest of
+#'   assertions.
 #' @export
-#' @examples assert('one equals one', 1==1)
+#' @examples ## The first way to write assertions --------------------
+#'
+#' assert('one equals one', 1==1)
 #' assert('seq and : produce equal sequences', seq(1L, 10L) == 1L:10L)
 #' assert('seq and : produce identical sequences', identical(seq(1L, 10L), 1L:10L))
 #'
-#' # multile tests
+#' # multiple tests
 #' T=FALSE; F=TRUE
 #' assert('T is bad for TRUE, and so is F for FALSE', T!=TRUE, F!=FALSE)
 #'
@@ -39,15 +58,54 @@
 #'
 #' # no message
 #' assert(!FALSE, TRUE, is.na(NA))
+#'
+#'
+#' ## The second way to write assertions -------------------
+#'
+#' assert('T is bad for TRUE, and so is F for FALSE', {T=FALSE;F=TRUE
+#' (T!=TRUE)  # note the parentheses
+#' (F!=FALSE)})
+#'
+#' assert('A Poisson random number is non-negative', {
+#' x = rpois(1, 10)
+#' (x >= 0)
+#' x > -1  # do not need () here because it's the last expression
+#' })
 assert = function(fact, ...) {
-  fact_char = is.character(fact)
-  n = length(ll <- if (fact_char) list(...) else list(fact, ...))
-  if (n == 0L) return(invisible())
-  mc = match.call(); if (fact_char) mc[['fact']] = NULL
-  for (i in 1L:n) if (!all_true(r <- ll[[i]])) {
-    if (fact_char) message('assertion failed: ', fact)
-    stop(sprintf(ngettext(length(r), '%s is not TRUE', '%s are not all TRUE'),
-                 deparse_key(mc[[i + 1]])), call. = FALSE, domain = NA)
+  mc = match.call()
+  # match.call() uses the arg order in the func def, so fact is always 1st arg
+  fact = NULL
+  if (is.character(mc[[2]])) {
+    fact = mc[[2]]; mc = mc[-2]
+  }
+  one = one_expression(mc)
+  assert2(fact, if (one) mc[[2]][-1] else mc[-1], parent.frame(), !one)
+}
+
+# whether the argument of a function call is a single expression in {}
+one_expression = function(call) {
+  length(call) == 2 && length(call[[2]]) >= 1 && identical(call[[c(2, 1)]], as.symbol('{'))
+}
+
+assert2 = function(fact, exprs, envir, all = TRUE) {
+  n = length(exprs)
+  for (i in seq_len(n)) {
+    expr = exprs[[i]]
+    val = eval(expr, envir = envir, enclos = NULL)
+    # special case: fact is an expression instead of a string constant in assert()
+    if (is.null(fact) && all && i == 1 && is.character(val)) {
+      fact = val; next
+    }
+    # check all values in case of multiple arguments, o/w only check values in ()
+    if (all || (i == n && is.logical(val)) ||
+        (length(expr) >= 1 && identical(expr[[1]], as.symbol('(')))) {
+      if (all_true(val)) next
+      if (!is.null(fact)) message('assertion failed: ', fact)
+      stop(sprintf(
+        ngettext(length(val), '%s is not TRUE', '%s are not all TRUE'),
+        deparse_key(expr)
+      ), call. = FALSE, domain = NA)
+    }
   }
 }
 
@@ -99,7 +157,7 @@ test_pkg = function(package, dir = 'testit') {
     withCallingHandlers(
       sys.source2(r, envir = env, top.env = getNamespace(package)),
       error = function(e) {
-        z = .traceback(4)
+        z = .traceback(5)
         if (length(z) == 0) return()
         z = z[[1]]
         n = length(z)
diff --git a/README.md b/README.md
index cf76eaa..319647a 100644
--- a/README.md
+++ b/README.md
@@ -38,6 +38,11 @@ assert(
   'a non-exported function works',
   is.character(utility_foo(x = 'abcd', y = 1:100))
 )
+
+assert('T is TRUE and F is FALSE by default', {
+  (T == TRUE)
+  (F == FALSE)
+})
 ```
 
 ## R CMD check
@@ -52,7 +57,7 @@ test_pkg('pkg_name')
 ```
 
 That is all for `R CMD check`. For package development, it is recommended to
-use [**devtools**](https://CRAN.R-project.org/package=devtools). In
+use [**devtools**](https://cran.rstudio.org/package=devtools). In
 particular, `Ctrl + Shift + L` in RStudio makes all objects in a package
 visible to you, and you can play with the tests freely.
 
@@ -85,7 +90,7 @@ is the only single rule to remember.
 There is no plan to add new features or reinvent anything in this package.
 It is an intentionally tiny package.
 
-<img src="http://i.imgur.com/sDsgmfj.jpg" align="right" width="100" alt="Xunzi" />
+<img src="https://i.imgur.com/sDsgmfj.jpg" align="right" width="100" alt="Xunzi" />
 
 Although he did not really mean it,
 [Xunzi](http://en.wikipedia.org/wiki/Xunzi) said something that happens to
diff --git a/man/assert.Rd b/man/assert.Rd
index c0243df..c4a57c6 100644
--- a/man/assert.Rd
+++ b/man/assert.Rd
@@ -1,8 +1,9 @@
+% Generated by roxygen2: do not edit by hand
 % Please edit documentation in R/testit.R
 \name{assert}
-\alias{\%==\%}
 \alias{assert}
-\title{Assertions with a message}
+\alias{\%==\%}
+\title{Assertions with an optional message}
 \usage{
 assert(fact, ...)
 
@@ -13,8 +14,7 @@ x \%==\% y
 same way as expressions in \code{...} if it is not a character string,
 which means you do not have to provide a message to this function}
 
-\item{...}{any number of R expressions, presumably to return vectors of
-\code{TRUE}'s (if \code{FALSE} is returned anywhere, an error will show up)}
+\item{...}{any number of R expressions; see Details}
 
 \item{x, y}{two R objects to be compared}
 }
@@ -23,7 +23,7 @@ Invisible \code{NULL} if all expressions returned \code{TRUE},
   otherwise an error is signalled and the user-provided message is emitted.
 }
 \description{
-The function \code{assert()} was built from \code{\link{stopifnot}()}. It
+The function \code{assert()} was inspired by \code{\link{stopifnot}()}. It
 emits a message in case of errors, which can be a helpful hint for diagnosing
 the errors (\code{stopifnot()} only prints the possibly truncated source code
 of the expressions).
@@ -33,21 +33,42 @@ The infix operator \code{\%==\%} is simply an alias of the
   to write test conditions. \code{x \%==\% y} is the same as
   \code{identical(x, y)}.
 }
+\details{
+There are two ways to write R expressions in the \code{...} argument.
+
+The first way is a series of R expressions (each expression is passed as an
+individual argument) that return vectors of \code{TRUE}'s (if \code{FALSE} is
+returned anywhere, an error will show up).
+
+The second way is a single R expression wrapped in \code{{}} and passed as a
+single argument. This expression may contain multiple sub-expressions. A
+sub-expression is treated as a test condition if it is wrapped in \code{()}
+(meaning its value will be checked to see if it is a logical vector
+containing any \code{FALSE} values) , otherwise it is evaluated in the normal
+way and its value will not be checked. If the value of the last
+sub-expression is logical, it will also be treated as a test condition.
+}
 \note{
-The internal implementation of \code{stopifnot()} is different with the
-  function in R \pkg{base}: (1) the custom message \code{fact} is emitted if
-  an error occurs (2) \code{assert()} requires the logical values to be
-  non-empty (3) if \code{...} contains a compound expression in \code{{}}
-  which returns \code{FALSE} (e.g., \code{if (TRUE) {1+1; FALSE}}), the first
-  and the last but one line of the source code from \code{\link{deparse}()}
-  are printed in the error message, otherwise the first line is printed
+The internal implementation of \code{assert()} is different with the
+  \code{stopifnot()} function in R \pkg{base}: (1) the custom message
+  \code{fact} is emitted if an error occurs; (2) \code{assert()} requires the
+  logical values to be non-empty (\code{logical(0)} will trigger an error);
+  (3) if \code{...} contains a compound expression in \code{{}} that returns
+  \code{FALSE} (e.g., \code{if (TRUE) {1+1; FALSE}}), the first and the last
+  but one line of the source code from \code{\link{deparse}()} are printed in
+  the error message, otherwise the first line is printed; (4) the arguments
+  in \code{...} are evaluated sequentially, and \code{assert()} will signal
+  an error upon the first failed assertion, and will ignore the rest of
+  assertions.
 }
 \examples{
+## The first way to write assertions --------------------
+
 assert("one equals one", 1 == 1)
 assert("seq and : produce equal sequences", seq(1L, 10L) == 1L:10L)
 assert("seq and : produce identical sequences", identical(seq(1L, 10L), 1L:10L))
 
-# multile tests
+# multiple tests
 T = FALSE
 F = TRUE
 assert("T is bad for TRUE, and so is F for FALSE", T != TRUE, F != FALSE)
@@ -68,4 +89,20 @@ try(assert("this if statement returns TRUE", if (TRUE) {
 
 # no message
 assert(!FALSE, TRUE, is.na(NA))
+
+
+## The second way to write assertions -------------------
+
+assert("T is bad for TRUE, and so is F for FALSE", {
+    T = FALSE
+    F = TRUE
+    (T != TRUE)  # note the parentheses
+    (F != FALSE)
+})
+
+assert("A Poisson random number is non-negative", {
+    x = rpois(1, 10)
+    (x >= 0)
+    x > -1  # do not need () here because it's the last expression
+})
 }
diff --git a/man/has_message.Rd b/man/has_message.Rd
index cf7aad8..cf19327 100644
--- a/man/has_message.Rd
+++ b/man/has_message.Rd
@@ -1,7 +1,8 @@
+% Generated by roxygen2: do not edit by hand
 % Please edit documentation in R/testit.R
 \name{has_warning}
-\alias{has_error}
 \alias{has_warning}
+\alias{has_error}
 \title{Check if an R expression produces warnings or errors}
 \usage{
 has_warning(expr)
diff --git a/man/test_pkg.Rd b/man/test_pkg.Rd
index 0e0a5f4..7cb081b 100644
--- a/man/test_pkg.Rd
+++ b/man/test_pkg.Rd
@@ -1,3 +1,4 @@
+% Generated by roxygen2: do not edit by hand
 % Please edit documentation in R/testit.R
 \name{test_pkg}
 \alias{test_pkg}
diff --git a/tests/testit/test-assert.R b/tests/testit/test-assert.R
index 8d7791c..5408011 100644
--- a/tests/testit/test-assert.R
+++ b/tests/testit/test-assert.R
@@ -1,11 +1,11 @@
 library(testit)
 
-assert('assert works', 1==1)
+assert('assert works', 1 == 1)
 
 # Okay, that is kind of cheating
 assert(
   'assert() should signal an error if a condition does not hold',
-  has_error(assert('this should produce an error', 1==2))
+  has_error(assert('this should produce an error', 1 == 2))
 )
 
 # a meaningless test in terms of R (failure is irrelevant to Frequentist or Bayesian)
@@ -36,3 +36,14 @@ assert(
   has_error(stop('An intentional error')),
   has_error(1 + 'a')
 )
+
+assert('tests can be written in () in a single {}', {
+
+  (1 == 1L)
+
+  z = 1:10
+  (rev(z) %==% 10:1)
+
+  !!TRUE
+
+})

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-testit.git



More information about the debian-med-commit mailing list