[med-svn] [r-cran-testit] 03/05: New upstream version 0.6

Andreas Tille tille at debian.org
Fri Sep 29 14:54:22 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 5cf59d1ffad305b042124b5d77a2183f77a0942d
Author: Andreas Tille <tille at debian.org>
Date:   Fri Sep 29 16:52:58 2017 +0200

    New upstream version 0.6
---
 DESCRIPTION                   |  19 ++++++
 MD5                           |  14 +++++
 NAMESPACE                     |   5 ++
 NEWS                          |  64 +++++++++++++++++++
 R/testit.R                    | 140 ++++++++++++++++++++++++++++++++++++++++++
 R/utils.R                     |  44 +++++++++++++
 README.md                     |  96 +++++++++++++++++++++++++++++
 debian/README.test            |  10 ---
 debian/changelog              |  14 -----
 debian/compat                 |   1 -
 debian/control                |  22 -------
 debian/copyright              |  30 ---------
 debian/docs                   |   3 -
 debian/rules                  |  16 -----
 debian/source/format          |   1 -
 debian/tests/control          |   3 -
 debian/tests/run-unit-test    |  11 ----
 debian/watch                  |   2 -
 inst/rstudio/addins.dcf       |   4 ++
 man/assert.Rd                 |  71 +++++++++++++++++++++
 man/has_message.Rd            |  27 ++++++++
 man/test_pkg.Rd               |  48 +++++++++++++++
 tests/test-all.R              |   3 +
 tests/test-error/test-error.R |   1 +
 tests/testit/test-assert.R    |  38 ++++++++++++
 tests/testit/test-utils.R     |  22 +++++++
 26 files changed, 596 insertions(+), 113 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
new file mode 100644
index 0000000..c17949e
--- /dev/null
+++ b/DESCRIPTION
@@ -0,0 +1,19 @@
+Package: testit
+Type: Package
+Title: A Simple Package for Testing R Packages
+Version: 0.6
+Date: 2016-11-09
+Author: Yihui Xie
+Maintainer: Yihui Xie <xie at yihui.name>
+Description: Provides two convenience functions assert() and test_pkg() to
+    facilitate testing R packages.
+License: GPL
+URL: https://github.com/yihui/testit
+BugReports: https://github.com/yihui/testit/issues
+Suggests: rstudioapi
+Collate: 'testit.R' 'utils.R'
+RoxygenNote: 5.0.1
+NeedsCompilation: no
+Packaged: 2016-11-08 21:51:20 UTC; yihui
+Repository: CRAN
+Date/Publication: 2016-11-09 18:28:59
diff --git a/MD5 b/MD5
new file mode 100644
index 0000000..e55b45f
--- /dev/null
+++ b/MD5
@@ -0,0 +1,14 @@
+c210b4a01bde165c812cfcef436a8b65 *DESCRIPTION
+2a706e1aaf23d48acdbbc7ff8ff87005 *NAMESPACE
+ea78f195a2427276a1cbda53c65d2313 *NEWS
+1169a417364bc75090bac943082be032 *R/testit.R
+c24fd4cbad5d330a945a9e04cd75822b *R/utils.R
+7d92568615093174e38db7bd80452db8 *README.md
+4aae9b69bfa4f9baa95bd50f98274ba3 *inst/rstudio/addins.dcf
+d39845785bc048cefcec31007bcd918a *man/assert.Rd
+7e8dd84fd84aa824305aeec560ef65a6 *man/has_message.Rd
+32621e7874660ff8c5eb228102bb2a93 *man/test_pkg.Rd
+fc95de596ff143707ce5da2874086a92 *tests/test-all.R
+5330c047ff926dcaf08d9266db9a71f8 *tests/test-error/test-error.R
+0910ad4200cb30bee30cd73ab59fe63b *tests/testit/test-assert.R
+e058e991696d0946fdf35e115fbf3dc0 *tests/testit/test-utils.R
diff --git a/NAMESPACE b/NAMESPACE
new file mode 100644
index 0000000..ef4f56b
--- /dev/null
+++ b/NAMESPACE
@@ -0,0 +1,5 @@
+export("%==%")
+export(assert)
+export(has_error)
+export(has_warning)
+export(test_pkg)
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..70f29aa
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,64 @@
+    CHANGES IN testit VERSION 0.6
+
+NEW FEATURES
+
+  o  test_pkg() runs package tests with top-level environment being set to the
+  namespace of the tested package (thanks, @kalibera, #3)
+
+MAJOR CHANGES
+
+  o all test scripts (test-*.R) are assumed to be encoded in UTF-8 if they
+  contain multibyte characters
+
+    CHANGES IN testit VERSION 0.5
+
+NEW FEATURES
+
+  o added an infix operator `%==%` as an alias of identical() (in RStudio, you
+  can use an add-in to insert the text `%==%`)
+
+MINOR CHANGES
+
+  o test_pkg() will print out the filename of the R script that errored
+
+    CHANGES IN testit VERSION 0.4
+
+MAJOR CHANGES
+
+  o the `fact` argument of `assert()` is optional now: all arguments of
+  `assert()` can be test conditions
+
+    CHANGES IN testit VERSION 0.3
+
+MAJOR CHANGES
+
+  o the test files have to be named of the form test-*.R (or test-*.r), i.e.
+    they have to use the prefix test-
+
+  o the test environment is always cleaned (all objects removed) before the
+    next test is run
+
+    CHANGES IN testit VERSION 0.2.1
+
+MINOR CHANGES
+
+  o fixed a test that failed under R 2.15.x because the argument keep.source
+    did not exist in parse()
+
+    CHANGES IN testit VERSION 0.2
+
+MAJOR CHANGES
+
+  o assert() does not use base::stopifnot() any more; a tailored version of
+    stopifnot() is used now; see ?assert for the differences between this
+    version and base::stopifnot(); in particular, assert(fact, logical(0))
+    will fail but stopifnot(logical(0)) will not
+
+    CHANGES IN testit VERSION 0.1
+
+NEW FEATURES
+
+  o this is the first version of testit; the source code is hosted on
+    Github: https://github.com/yihui/testit
+
+  o added functions assert(), test_pkg(), has_error() and has_warning()
diff --git a/R/testit.R b/R/testit.R
new file mode 100644
index 0000000..db33974
--- /dev/null
+++ b/R/testit.R
@@ -0,0 +1,140 @@
+#' Assertions with a message
+#'
+#' The function \code{assert()} was built from \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).
+#' @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)
+#' @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
+#' @export
+#' @examples 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
+#' T=FALSE; F=TRUE
+#' assert('T is bad for TRUE, and so is F for FALSE', T!=TRUE, F!=FALSE)
+#'
+#' # a mixture of tests
+#' assert("Let's pray all of them will pass", 1==1, 1!=2, letters[4]=='d', rev(rev(letters))==letters)
+#'
+#' # logical(0) cannot pass assert(), although stopifnot() does not care
+#' try(assert('logical(0) cannot pass', 1==integer(0)))
+#' stopifnot(1==integer(0)) # it's OK!
+#'
+#' # a compound expression
+#' try(assert('this if statement returns TRUE', if(TRUE){x=1;x==2}))
+#'
+#' # no message
+#' assert(!FALSE, TRUE, is.na(NA))
+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)
+  }
+}
+
+#' @description The infix operator \code{\%==\%} is simply an alias of the
+#'   \code{\link{identical}()} function to make it slightly easier and intuitive
+#'   to write test conditions. \code{x \%==\% y} is the same as
+#'   \code{identical(x, y)}.
+#' @param x,y two R objects to be compared
+#' @rdname assert
+#' @export
+`%==%` = function(x, y) identical(x, y)
+
+#' Run the tests of a package in its namespace
+#'
+#' The main purpose of this function is to expose the namespace of a package
+#' when running tests, which allows one to use non-exported objects in the
+#' package without having to resort to the triple colon \code{\link{:::}} trick.
+#'
+#' The tests are assumed to be under the \file{testit/} directory by default,
+#' and this function also looks for the \file{tests/testit/} directory under the
+#' package installation directory when the user-provided \code{dir} does not
+#' exist. The test scripts must be named of the form \samp{test-*.R}; other R
+#' scripts will not be treated as test files (but may also be useful, e.g. you
+#' can \code{\link{source}()} them in tests).
+#'
+#' For \command{R CMD check}, this means the test R scripts (\file{test-*.R} are
+#' under \file{pkg_root/tests/testit/}. The R scripts are executed with
+#' \code{\link{sys.source}} in the namespace of the package to be tested; when
+#' an R script is executed, the working directory is the same as the directory
+#' containing this script, and all existing objects in the test environment will
+#' be removed before the code is executed.
+#' @param package the package name
+#' @param dir the directory of the test files; by default, it is the directory
+#'   \file{testit/} under the current working directory
+#' @return \code{NULL}. All test files are executed, unless an error occurs.
+#' @note All test scripts (\samp{test-*.R}) must be encoded in UTF-8 if they
+#'   contain any multibyte characters.
+#' @seealso The \pkg{testthat} package (much more sophisticated).
+#' @export
+#' @examples \dontrun{test_pkg('testit')}
+test_pkg = function(package, dir = 'testit') {
+  library(package, character.only = TRUE)
+  path = available_dir(c(dir, system.file('tests', 'testit', package = package)))
+  rs = list.files(path, '^test-.+[.][rR]$', full.names = TRUE)
+  # make all objects in the package visible to tests
+  env = new.env(parent = getNamespace(package))
+  for (r in rs) {
+    rm(list = ls(env, all.names = TRUE), envir = env)
+    withCallingHandlers(
+      sys.source2(r, envir = env, top.env = getNamespace(package)),
+      error = function(e) {
+        z = .traceback(4)
+        if (length(z) == 0) return()
+        z = z[[1]]
+        n = length(z)
+        s = if (!is.null(srcref <- attr(z, 'srcref'))) {
+          paste0(' at ', basename(attr(srcref, 'srcfile')$filename), '#', srcref[1])
+        }
+        z[n] = paste0(z[n], s)
+        cat(z, sep = '\n')
+      }
+    )
+  }
+}
+
+#' Check if an R expression produces warnings or errors
+#'
+#' The two functions \code{has_warning()} and \code{has_error()} check if an
+#' expression produces warnings and errors, respectively.
+#' @param expr an R expression
+#' @return A logical value.
+#' @export
+#' @rdname has_message
+#' @examples has_warning(1+1); has_warning(1:2+1:3)
+#'
+#' has_error(2-3); has_error(1+'a')
+has_warning = function(expr) {
+  warn = FALSE
+  op = options(warn = -1); on.exit(options(op))
+  withCallingHandlers(expr, warning = function(w) {
+    warn <<- TRUE
+    invokeRestart('muffleWarning')
+  })
+  warn
+}
+#' @export
+#' @rdname has_message
+has_error = function(expr) {
+  inherits(try(force(expr), silent = !interactive()), 'try-error')
+}
diff --git a/R/utils.R b/R/utils.R
new file mode 100644
index 0000000..281a302
--- /dev/null
+++ b/R/utils.R
@@ -0,0 +1,44 @@
+# find an available dir
+available_dir = function(dirs) {
+  for (i in dirs) {
+    if (utils::file_test('-d', i)) return(i)
+  }
+  stop('none of the directories exists:\n', paste(utils::formatUL(dirs), collapse = '\n'))
+}
+
+# tailored for assert(): extract the expression that is likely to be useful for
+# diagnostics if possible
+deparse_key = function(expr) {
+  x = deparse(expr, width.cutoff = 100L)
+  if ((n <- length(x)) <= 1) return(x)
+  # if expression is in {}, fetch the line n-1, otherwise use the first line
+  paste(x[1], '....', if (x[n] == '}') sub('^\\s*', '', x[n - 1L]))
+}
+
+# whether every element of x is strictly TRUE
+all_true = function(x) {
+  is.logical(x) && length(x) && !any(is.na(x)) && all(x)
+}
+
+insert_identical = function() {
+  if (!has_error(rstudioapi::verifyAvailable()))
+    rstudioapi::insertText(text = ' %==% ')
+}
+
+# This function is a modification of base::sys.source.  It allows to specify
+# the top-level environment, which is by default "envir" (the same as in
+# base::sys.source), but for package testing it is desirable to use the
+# package namespace to mimick the environment structure used when packages
+# are running. This function assumes that chdir = FALSE and keep.source = TRUE.
+sys.source2 = function(file, envir, top.env = as.environment(envir)) {
+  oop = options(keep.source = TRUE, topLevelEnvironment = top.env)
+  on.exit(options(oop))
+
+  lines = readLines(file, warn = FALSE, encoding = 'UTF-8')
+  srcfile = srcfilecopy(file, lines, file.mtime(file), isFile = TRUE)
+  exprs = parse(text = lines, srcfile = srcfile, encoding = 'UTF-8')
+
+  if (length(exprs) == 0L) return()
+  owd = setwd(dirname(file)); on.exit(setwd(owd), add = TRUE)
+  for (i in seq_along(exprs)) eval(exprs[i], envir)
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cf76eaa
--- /dev/null
+++ b/README.md
@@ -0,0 +1,96 @@
+# testit
+
+[![Build Status](https://travis-ci.org/yihui/testit.svg)](https://travis-ci.org/yihui/testit)
+[![Coverage Status](https://coveralls.io/repos/github/yihui/testit/badge.svg?branch=master)](https://coveralls.io/github/yihui/testit?branch=master)
+
+This package provides two simple functions (30 lines of code in total):
+
+- `assert(fact, ...)`: think of it as `message(fact)` + `stopifnot(...)`
+
+- `test_pkg(package)`: runs tests with all objects (exported or
+  non-exported) in the package namespace directly available, so no need to
+  use `package:::name` for non-exported objects
+
+## Why?
+
+The reason is laziness. It is tedious to type these commands repeatedly in
+tests:
+
+```r
+message('checking if these numbers are equal...')
+stopifnot(all.equal(1, 1+1e-10), 10*.1 == 1)
+
+message('checking if a non-exported function works...')
+stopifnot(is.character(package:::utility_foo(x = 'abcd', y = 1:100)))
+```
+
+With the two simple functions above, we type six letters (`assert`) instead
+of sixteen (`message` + `stopifnot`), and `assert` is also a more intuitive
+function name for testing purposes (you _assert_ a fact followed by evidence):
+
+```r
+assert(
+  'these numbers are equal',
+  all.equal(1, 1+1e-10), 10*.1 == 1
+)
+
+assert(
+  'a non-exported function works',
+  is.character(utility_foo(x = 'abcd', y = 1:100))
+)
+```
+
+## R CMD check
+
+Put the tests under the directory `pkg_name/tests/testit/` (where `pkg_name`
+is the root directory of your package), and write a `test-all.R` under
+`pkg_name/tests/`:
+
+```r
+library(testit)
+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
+particular, `Ctrl + Shift + L` in RStudio makes all objects in a package
+visible to you, and you can play with the tests freely.
+
+## Installation
+
+Stable version on CRAN:
+
+```r
+install.packages('testit')
+```
+
+Development version:
+
+```r
+devtools::install_github('yihui/testit')
+```
+
+## More
+
+How about [**testthat**](https://CRAN.R-project.org/package=testthat)? Well,
+this package is far less sophisticated than **testthat**. There is nothing
+fancy in this package. Please do consider **testthat** if your tests require
+more granularity. I myself do not use **testthat** because I find it unnecessary
+to invent a new vocabulary (`testthat::expect_xxx`), and the error message of
+**testthat** is somehow obscure in my eyes. For **testit**, I do not need to
+think if I should use `expect_equal`, `expect_equivalent`, or
+`expect_identical`; I just write test conditions that return TRUE or FALSE. That
+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" />
+
+Although he did not really mean it,
+[Xunzi](http://en.wikipedia.org/wiki/Xunzi) said something that happens to
+apply well to unit testing:
+
+> 不积跬步,无以至千里;不积小流,无以成江海。
+
+This package is free and open source software, licensed under GPL.
diff --git a/debian/README.test b/debian/README.test
deleted file mode 100644
index 3d2b347..0000000
--- a/debian/README.test
+++ /dev/null
@@ -1,10 +0,0 @@
-Notes on how this package can be tested.
-────────────────────────────────────────
-
-To run the unit tests provided by the package you can do
-
-   sh run-unit-test
-
-in this directory.
-
-
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index ef643ee..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,14 +0,0 @@
-r-cran-testit (0.6-1) unstable; urgency=medium
-
-  * New upstream version
-  * Convert to dh-r
-  * Canonical homepage for CRAN
-  * d/watch: version=4
-
- -- Andreas Tille <tille at debian.org>  Thu, 10 Nov 2016 21:20:46 +0100
-
-r-cran-testit (0.5-1) unstable; urgency=low
-
-  * Initial release (closes: #837342)
-
- -- Andreas Tille <tille at debian.org>  Sat, 10 Sep 2016 20:51:36 +0200
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
deleted file mode 100644
index af956ce..0000000
--- a/debian/control
+++ /dev/null
@@ -1,22 +0,0 @@
-Source: r-cran-testit
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Andreas Tille <tille at debian.org>
-Section: gnu-r
-Priority: optional
-Build-Depends: debhelper (>= 9),
-               dh-r,
-               r-base-dev
-Standards-Version: 3.9.8
-Vcs-Browser: https://anonscm.debian.org/viewvc/debian-med/trunk/packages/R/r-cran-testit/trunk/
-Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/R/r-cran-testit/trunk/
-Homepage: https://cran.r-project.org/package=testit
-
-Package: r-cran-testit
-Architecture: all
-Depends: ${R:Depends},
-         ${misc:Depends}
-Recommends: ${R:Recommends}
-Suggests: ${R:Suggests}
-Description: simple package for testing GNU R packages
- This GNU R package provides two convenience functions assert() and
- test_pkg() to facilitate testing R packages.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index 121fe6c..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,30 +0,0 @@
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Contact: Yihui Xie <xie at yihui.name>
-Upstream-Name: testit
-Source: https://cran.r-project.org/package=testit
-
-Files: *
-Copyright: 2014-2016 Yihui Xie <xie at yihui.name>
-License: GPL-2+
-
-Files: debian/*
-Copyright: 2016 Andreas Tille <tille at debian.org>
-License: GPL-2+
-
-License: GPL-2+
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
- .
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
- .
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- .
- On Debian systems, the complete text of the GNU General Public
- License can be found in `/usr/share/common-licenses/GPL-2'.
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index 960011c..0000000
--- a/debian/docs
+++ /dev/null
@@ -1,3 +0,0 @@
-tests
-debian/README.test
-debian/tests/run-unit-test
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index 12f114f..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/make -f
-
-%:
-	dh $@ --buildsystem R
-
-override_dh_install:
-	dh_install
-	find debian -name LICENSE -delete
-
-# needs checking idea whether this is needed any more
-    # Delete tests depending from devtools since this is not (yet) packaged
-#	cd debian/$(package)/usr/share/doc/$(package)/tests/ ; \
-#	if grep -qR devtools * ; then \
-#	    rm -f `grep -lR devtools *` ; \
-#	fi
-
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/tests/control b/debian/tests/control
deleted file mode 100644
index d2aa55a..0000000
--- a/debian/tests/control
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests: run-unit-test
-Depends: @
-Restrictions: allow-stderr
diff --git a/debian/tests/run-unit-test b/debian/tests/run-unit-test
deleted file mode 100644
index d89d16d..0000000
--- a/debian/tests/run-unit-test
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh -e
-
-pkg=r-cran-testit
-if [ "$ADTTMP" = "" ] ; then
-  ADTTMP=`mktemp -d /tmp/${pkg}-test.XXXXXX`
-  trap "rm -rf $ADTTMP" 0 INT QUIT ABRT PIPE TERM
-fi
-cd $ADTTMP
-cp -a /usr/share/doc/${pkg}/tests/* .
-
-LC_ALL=C R --no-save < test-all.R
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index dc9e63e..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,2 +0,0 @@
-version=4
-http://cran.r-project.org/src/contrib/testit_([-\d.]*)\.tar\.gz
diff --git a/inst/rstudio/addins.dcf b/inst/rstudio/addins.dcf
new file mode 100644
index 0000000..aaa7a5b
--- /dev/null
+++ b/inst/rstudio/addins.dcf
@@ -0,0 +1,4 @@
+Name: Insert %==%
+Description: Insert the infix operator %==% from testit.
+Binding: insert_identical
+Interactive: false
diff --git a/man/assert.Rd b/man/assert.Rd
new file mode 100644
index 0000000..c0243df
--- /dev/null
+++ b/man/assert.Rd
@@ -0,0 +1,71 @@
+% Please edit documentation in R/testit.R
+\name{assert}
+\alias{\%==\%}
+\alias{assert}
+\title{Assertions with a message}
+\usage{
+assert(fact, ...)
+
+x \%==\% y
+}
+\arguments{
+\item{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}
+
+\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{x, y}{two R objects to be compared}
+}
+\value{
+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
+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).
+
+The infix operator \code{\%==\%} is simply an alias of the
+  \code{\link{identical}()} function to make it slightly easier and intuitive
+  to write test conditions. \code{x \%==\% y} is the same as
+  \code{identical(x, y)}.
+}
+\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
+}
+\examples{
+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
+T = FALSE
+F = TRUE
+assert("T is bad for TRUE, and so is F for FALSE", T != TRUE, F != FALSE)
+
+# a mixture of tests
+assert("Let's pray all of them will pass", 1 == 1, 1 != 2, letters[4] == "d", 
+    rev(rev(letters)) == letters)
+
+# logical(0) cannot pass assert(), although stopifnot() does not care
+try(assert("logical(0) cannot pass", 1 == integer(0)))
+stopifnot(1 == integer(0))  # it's OK!
+
+# a compound expression
+try(assert("this if statement returns TRUE", if (TRUE) {
+    x = 1
+    x == 2
+}))
+
+# no message
+assert(!FALSE, TRUE, is.na(NA))
+}
diff --git a/man/has_message.Rd b/man/has_message.Rd
new file mode 100644
index 0000000..cf7aad8
--- /dev/null
+++ b/man/has_message.Rd
@@ -0,0 +1,27 @@
+% Please edit documentation in R/testit.R
+\name{has_warning}
+\alias{has_error}
+\alias{has_warning}
+\title{Check if an R expression produces warnings or errors}
+\usage{
+has_warning(expr)
+
+has_error(expr)
+}
+\arguments{
+\item{expr}{an R expression}
+}
+\value{
+A logical value.
+}
+\description{
+The two functions \code{has_warning()} and \code{has_error()} check if an
+expression produces warnings and errors, respectively.
+}
+\examples{
+has_warning(1 + 1)
+has_warning(1:2 + 1:3)
+
+has_error(2 - 3)
+has_error(1 + "a")
+}
diff --git a/man/test_pkg.Rd b/man/test_pkg.Rd
new file mode 100644
index 0000000..0e0a5f4
--- /dev/null
+++ b/man/test_pkg.Rd
@@ -0,0 +1,48 @@
+% Please edit documentation in R/testit.R
+\name{test_pkg}
+\alias{test_pkg}
+\title{Run the tests of a package in its namespace}
+\usage{
+test_pkg(package, dir = "testit")
+}
+\arguments{
+\item{package}{the package name}
+
+\item{dir}{the directory of the test files; by default, it is the directory
+\file{testit/} under the current working directory}
+}
+\value{
+\code{NULL}. All test files are executed, unless an error occurs.
+}
+\description{
+The main purpose of this function is to expose the namespace of a package
+when running tests, which allows one to use non-exported objects in the
+package without having to resort to the triple colon \code{\link{:::}} trick.
+}
+\details{
+The tests are assumed to be under the \file{testit/} directory by default,
+and this function also looks for the \file{tests/testit/} directory under the
+package installation directory when the user-provided \code{dir} does not
+exist. The test scripts must be named of the form \samp{test-*.R}; other R
+scripts will not be treated as test files (but may also be useful, e.g. you
+can \code{\link{source}()} them in tests).
+
+For \command{R CMD check}, this means the test R scripts (\file{test-*.R} are
+under \file{pkg_root/tests/testit/}. The R scripts are executed with
+\code{\link{sys.source}} in the namespace of the package to be tested; when
+an R script is executed, the working directory is the same as the directory
+containing this script, and all existing objects in the test environment will
+be removed before the code is executed.
+}
+\note{
+All test scripts (\samp{test-*.R}) must be encoded in UTF-8 if they
+  contain any multibyte characters.
+}
+\examples{
+\dontrun{
+test_pkg("testit")
+}
+}
+\seealso{
+The \pkg{testthat} package (much more sophisticated).
+}
diff --git a/tests/test-all.R b/tests/test-all.R
new file mode 100644
index 0000000..44b53c2
--- /dev/null
+++ b/tests/test-all.R
@@ -0,0 +1,3 @@
+library(testit)
+test_pkg('testit')
+try(test_pkg('testit', 'test-error'))
diff --git a/tests/test-error/test-error.R b/tests/test-error/test-error.R
new file mode 100644
index 0000000..064b053
--- /dev/null
+++ b/tests/test-error/test-error.R
@@ -0,0 +1 @@
+stop('An intentional error!')
diff --git a/tests/testit/test-assert.R b/tests/testit/test-assert.R
new file mode 100644
index 0000000..8d7791c
--- /dev/null
+++ b/tests/testit/test-assert.R
@@ -0,0 +1,38 @@
+library(testit)
+
+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))
+)
+
+# a meaningless test in terms of R (failure is irrelevant to Frequentist or Bayesian)
+try(assert(
+  'Frequentists must be correct (http://xkcd.com/1132/)',
+  'The sun has exploded!', sample(6, 2) == c(6, 6)
+), silent = !interactive())
+
+# fail logical(0)
+assert(
+  'assert() should stop on logical(0)',
+  has_error(assert('1 equals integer(0)', 1 == integer(0)))
+)
+
+assert(
+  'the infix operator %==% works',
+  1 %==% 1, !(1 %==% 1L)
+)
+
+assert(
+  'has_warning() works',
+  has_warning(warning('An intentional warning')),
+  has_warning((function() {1:2 + 1:3})())
+)
+
+assert(
+  'has_error() works',
+  has_error(stop('An intentional error')),
+  has_error(1 + 'a')
+)
diff --git a/tests/testit/test-utils.R b/tests/testit/test-utils.R
new file mode 100644
index 0000000..bb50959
--- /dev/null
+++ b/tests/testit/test-utils.R
@@ -0,0 +1,22 @@
+library(testit)
+
+# no need to use testit:::available_dir()
+assert(
+  'available_dir() should find an existing directory',
+  file.exists(
+    available_dir(c('foobar', 'whatever', '~', system.file('man', package = 'testit')))
+  ),
+  has_error(available_dir('asdfasdf'))
+)
+
+exprs = parse(text = 'if (TRUE) {T&F}\n1+1')
+assert(
+  'deparse_key() fetches the n-1 element if code is in {}',
+  deparse_key(exprs[[1]]) == 'if (TRUE) { .... T & F'
+)
+assert(
+  'deparse_key() returns the parsed code if length == 1',
+  deparse_key(exprs[[2]]) == '1 + 1'
+)
+
+insert_identical()

-- 
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