The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Testing and checking packages with srcpkgs

I will demonstrate srcpkgs using a dummy collection of source packages: https://github.com/kforner/srcpkgs_lotr_demo It consists currently in 11 related packages, with internal dependencies. The dependencies are implemented by a mix of Imports, Imports with namespace imports and Depends.

listing the LOTR collection of packages with srcpkgs

library(srcpkgs)
print(names(get_srcpkgs()))
##  [1] "aragorn"   "bilbo"     "elrond"    "elves"     "frodo"     "galadriel"
##  [7] "gandalf"   "gimli"     "hobbits"   "legolas"   "lotr"
# cat(clitable::cli_table(as.data.frame(get_srcpkgs())), sep = "\n")

testing the collection

no tests yet

The LOTR collection does not come with any test. Let’s see what happens then…

print(pkgs_test(reporter = "silent"))
## 
## ── Test results by package ─────────────────────────────────────────────────────
## ╒═════════╤══╤══════╤══════╤═══════╤═════╤═══════╤════╕
## │ package │nb│failed│passed│skipped│error│warning│time│
## ╞═════════╪══╪══════╪══════╪═══════╪═════╪═══════╪════╡
## │ aragorn │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │ bilbo   │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │ elrond  │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │ elves   │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │ frodo   │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │galadriel│ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │ gandalf │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │ gimli   │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │ hobbits │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │ legolas │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## │ lotr    │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## ╘═════════╧══╧══════╧══════╧═══════╧═════╧═══════╧════╛
## 
## ── Test results overview ───────────────────────────────────────────────────────
## ╒═══════╤══╤══════╤══════╤═══════╤═════╤═══════╤════╕
## │package│nb│failed│passed│skipped│error│warning│time│
## ╞═══════╪══╪══════╪══════╪═══════╪═════╪═══════╪════╡
## │ 11    │ 0│ 0    │ 0    │ 0     │ 0   │ 0     │ 0  │
## ╘═══════╧══╧══════╧══════╧═══════╧═════╧═══════╧════╛
## 
## SUCCESS

So no tests (nb == 0) but the testing was successful since no test failed…

adding dummy tests to the packages

Let’s add programmatically some dummy tests to our packages.

add_dummy_test_to_srcpkg <- function(srcpkg, with_failures = TRUE, with_errors = TRUE, with_warnings = TRUE) {
  withr::local_dir(srcpkg$path)
  dir.create("tests/testthat", recursive = TRUE, showWarnings = FALSE)

  .write_test <- function(name, code, test = name) {
    writeLines(sprintf(r"-----{
    test_that("%s", {
      %s
    })
    }-----", name, code), sprintf("tests/testthat/test-%s.R", test))
  }

  .write_test("success", "expect_true(TRUE)")
  if (with_failures) {
    .write_test("failure", "expect_true(FALSE)")
    .write_test("mixed", "expect_true(FALSE);expect_true(TRUE)")
  }
  .write_test("skip", 'skip("skipping");expect_true(FALSE)')
  if (with_errors) .write_test("errors", 'expect_true(TRUE);stop("Arghh");expect_true(TRUE)')
  if (with_warnings)  .write_test("warning", 'expect_true(FALSE);warning("watch out");expect_true(FALSE)')
  if (with_failures && with_errors)
    writeLines(r"-----{
    test_that("misc1", {
      expect_true(FALSE)
      expect_true(TRUE)
    })
    test_that("misc2", {
      expect_true(FALSE)
      skip("skipping")
    })
    test_that("misc3", {
      expect_true(TRUE)
      expect_true(TRUE)
    })
    test_that("misc4", {
      expect_true(TRUE)
      warning("fais gaffe")
      stop("aie")
      expect_true(TRUE)
    })
    }-----", "tests/testthat/test-misc.R")

  writeLines(sprintf(r"-----{
    library(testthat)
    library(%s)

    test_check("%s")
  }-----", srcpkg$package, srcpkg$package), "tests/testthat.R")
}
i <- 0
for (pkg in get_srcpkgs()) {
  add_dummy_test_to_srcpkg(pkg, i %% 3 == 1, i %% 7 == 1, i %% 5 == 1)
  i <- i + 1
}

testing

Now let’s test again.

# N.B: we use the silent testthat reporter because we only want to get the results as tables
test_results <- pkgs_test(reporter = "silent")
print(test_results)
## 
## ── Test results by package ─────────────────────────────────────────────────────
## ╒═════════╤══╤══════╤══════╤═══════╤═════╤═══════╤═════╕
## │ package │nb│failed│passed│skipped│error│warning│ time│
## ╞═════════╪══╪══════╪══════╪═══════╪═════╪═══════╪═════╡
## │ aragorn │ 2│ 0    │ 1    │ 1     │ 0   │ 0     │ 0.02│
## │ bilbo   │17│ 6    │ 7    │ 2     │ 2   │ 2     │0.243│
## │ elrond  │ 2│ 0    │ 1    │ 1     │ 0   │ 0     │0.007│
## │ elves   │ 2│ 0    │ 1    │ 1     │ 0   │ 0     │0.007│
## │ frodo   │ 5│ 2    │ 2    │ 1     │ 0   │ 0     │ 0.04│
## │galadriel│ 2│ 0    │ 1    │ 1     │ 0   │ 0     │0.007│
## │ gandalf │ 5│ 2    │ 1    │ 1     │ 0   │ 1     │ 0.04│
## │ gimli   │ 5│ 2    │ 2    │ 1     │ 0   │ 0     │0.041│
## │ hobbits │ 3│ 0    │ 2    │ 1     │ 1   │ 0     │0.019│
## │ legolas │ 2│ 0    │ 1    │ 1     │ 0   │ 0     │0.007│
## │ lotr    │ 5│ 2    │ 2    │ 1     │ 0   │ 0     │0.041│
## ╘═════════╧══╧══════╧══════╧═══════╧═════╧═══════╧═════╛
## 
## ── Test results overview ───────────────────────────────────────────────────────
## ╒═══════╤══╤══════╤══════╤═══════╤═════╤═══════╤═════╕
## │package│nb│failed│passed│skipped│error│warning│ time│
## ╞═══════╪══╪══════╪══════╪═══════╪═════╪═══════╪═════╡
## │ 11    │50│ 14   │ 21   │ 12    │ 3   │ 3     │0.472│
## ╘═══════╧══╧══════╧══════╧═══════╧═════╧═══════╧═════╛
## 
## FAILED

Note that in markdown we can not have the ANSI colors and formatting. Here’s a screenshot screenshot

using the test results

The test results are stored as a pkgs_test object, which is a list named after the packages, of pkg_test objects which are a subclass of testthat_results. You can manipulate them with S3 methods:

These S3 methods are also implemented for pkg_test objects.

print(as.data.frame(test_results))
##             package nb failed passed skipped error warning  time
## aragorn     aragorn  2      0      1       1     0       0 0.020
## bilbo         bilbo 17      6      7       2     2       2 0.243
## elrond       elrond  2      0      1       1     0       0 0.007
## elves         elves  2      0      1       1     0       0 0.007
## frodo         frodo  5      2      2       1     0       0 0.040
## galadriel galadriel  2      0      1       1     0       0 0.007
## gandalf     gandalf  5      2      1       1     0       1 0.040
## gimli         gimli  5      2      2       1     0       0 0.041
## hobbits     hobbits  3      0      2       1     1       0 0.019
## legolas     legolas  2      0      1       1     0       0 0.007
## lotr           lotr  5      2      2       1     0       0 0.041
print(summary(test_results))
##   package nb failed passed skipped error warning  time
## 1      11 50     14     21      12     3       3 0.472
print(as.logical(test_results))
## [1] FALSE
print(test_results$bilbo)
## 
## ── Test results by test for package bilbo ──────────────────────────────────────
## ╒═══════╤═══════╤══╤══════╤══════╤═══════╤═════╤═══════╤═════╕
## │ file  │ test  │nb│failed│passed│skipped│error│warning│ time│
## ╞═══════╪═══════╪══╪══════╪══════╪═══════╪═════╪═══════╪═════╡
## │ errors│ errors│ 1│ 0    │ 1    │ FALSE │ TRUE│ 0     │0.012│
## │failure│failure│ 1│ 1    │ 0    │ FALSE │FALSE│ 0     │0.077│
## │ misc  │ misc1 │ 2│ 1    │ 1    │ FALSE │FALSE│ 0     │0.036│
## │ misc  │ misc2 │ 2│ 1    │ 0    │ TRUE  │FALSE│ 0     │0.014│
## │ misc  │ misc3 │ 2│ 0    │ 2    │ FALSE │FALSE│ 0     │0.005│
## │ misc  │ misc4 │ 2│ 0    │ 1    │ FALSE │ TRUE│ 1     │0.028│
## │ mixed │ mixed │ 2│ 1    │ 1    │ FALSE │FALSE│ 0     │0.016│
## │ skip  │ skip  │ 1│ 0    │ 0    │ TRUE  │FALSE│ 0     │0.002│
## │success│success│ 1│ 0    │ 1    │ FALSE │FALSE│ 0     │0.004│
## │warning│warning│ 3│ 2    │ 0    │ FALSE │FALSE│ 1     │0.049│
## ╘═══════╧═══════╧══╧══════╧══════╧═══════╧═════╧═══════╧═════╛
## 
## ── Test results by file for package bilbo ──────────────────────────────────────
## ╒═══════╤══╤══════╤══════╤═══════╤═════╤═══════╤═════╕
## │ file  │nb│failed│passed│skipped│error│warning│ time│
## ╞═══════╪══╪══════╪══════╪═══════╪═════╪═══════╪═════╡
## │ errors│ 1│ 0    │ 1    │ 0     │ 1   │ 0     │0.012│
## │failure│ 1│ 1    │ 0    │ 0     │ 0   │ 0     │0.077│
## │ misc  │ 8│ 2    │ 4    │ 1     │ 1   │ 1     │0.083│
## │ mixed │ 2│ 1    │ 1    │ 0     │ 0   │ 0     │0.016│
## │ skip  │ 1│ 0    │ 0    │ 1     │ 0   │ 0     │0.002│
## │success│ 1│ 0    │ 1    │ 0     │ 0   │ 0     │0.004│
## │warning│ 3│ 2    │ 0    │ 0     │ 0   │ 1     │0.049│
## ╘═══════╧══╧══════╧══════╧═══════╧═════╧═══════╧═════╛
## 
## ── Test results overview for package bilbo ─────────────────────────────────────
## ╒══╤══════╤══════╤═══════╤═════╤═══════╤═════════════════╕
## │nb│failed│passed│skipped│error│warning│ time            │
## ╞══╪══════╪══════╪═══════╪═════╪═══════╪═════════════════╡
## │17│ 6    │ 7    │ 2     │ 2   │ 2     │0.243000000000001│
## ╘══╧══════╧══════╧═══════╧═════╧═══════╧═════════════════╛
print(as.data.frame(test_results$lotr))
##      file    test nb failed passed skipped error warning  time
## 1 failure failure  1      1      0   FALSE FALSE       0 0.018
## 2   mixed   mixed  2      1      1   FALSE FALSE       0 0.017
## 3    skip    skip  1      0      0    TRUE FALSE       0 0.002
## 4 success success  1      0      1   FALSE FALSE       0 0.004
print(summary(test_results$lotr))
##      file nb failed passed skipped error warning  time
## 1 failure  1      1      0       0     0       0 0.018
## 2   mixed  2      1      1       0     0       0 0.017
## 3    skip  1      0      0       1     0       0 0.002
## 4 success  1      0      1       0     0       0 0.004
print(as.logical(test_results$aragorn))
## [1] TRUE

checking the collection

Checking is very similar to testing except that it takes much longer! So we’ll use a small subset of the collection.

small_collection <- get_srcpkgs(filter = "elves|galadriel|legolas")

fixing the collection: declare testthat as dependency

.fix_description <- function(path, lst) {
  df <- read.dcf(path, all = TRUE)
  df2 <- utils::modifyList(df, lst)
  write.dcf(df2, path)
}
for (pkg in small_collection) {
  .fix_description(file.path(pkg$path, "DESCRIPTION"), list(Suggests = "testthat"))
}

checking the packages

check_results <- pkgs_check(small_collection, quiet = TRUE)
## ℹ Loading elves
## ℹ Loading galadriel
## ℹ Loading legolas
print(check_results)
## 
## ── Check results by package ────────────────────────────────────────────────────
## ╒═════════╤══════╤════════╤═════╤════╕
## │ package │errors│warnings│notes│time│
## ╞═════════╪══════╪════════╪═════╪════╡
## │ elves   │ 0    │ 0      │ 2   │7.26│
## │galadriel│ 0    │ 0      │ 2   │ 7  │
## │ legolas │ 0    │ 0      │ 2   │6.95│
## ╘═════════╧══════╧════════╧═════╧════╛
## 
## ── Check results overview ──────────────────────────────────────────────────────
## ╒═══════╤══════╤════════╤═════╤════╕
## │package│errors│warnings│notes│time│
## ╞═══════╪══════╪════════╪═════╪════╡
## │ 3     │ 0    │ 0      │ 6   │21.2│
## ╘═══════╧══════╧════════╧═════╧════╛
## 
## SUCCESS

using the check results

The check results are stored as a pkgs_check object, which is a list named after the packages, of pkg_check objects which are a subclass of rcmdcheck.

As with pkgs_test results, you can manipulate them with S3 methods:

print(as.data.frame(check_results))
##             package errors warnings notes     time
## elves         elves      0        0     2 7.258815
## galadriel galadriel      0        0     2 6.998296
## legolas     legolas      0        0     2 6.954053
print(summary(check_results))
##   package errors warnings notes     time
## 1       3      0        0     6 21.21116
print(as.logical(check_results))
## [1] TRUE
print(check_results$bilbo)
## NULL
print(as.data.frame(check_results$lotr))
## data frame with 0 columns and 0 rows
print(summary(check_results$lotr))
## Length  Class   Mode 
##      0   NULL   NULL
print(as.logical(check_results$aragorn))
## logical(0)

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.