[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