# load local package without installing it
::load_all()
devtools# Build the documentation (man pages)
::document()
devtools# Run the unit tests
::test()
devtools# Run coverage test
::test_coverage()
devtools# Build package source
::build()
devtools# Run package check
::check() devtools
(sources)
Several R packages to help you develop R packages.
R package ?
my_package
├── .Rbuildignore
├── _pkgdown.yml
├── DESCRIPTION
├── LICENSE.md
├── LICENSE.note
├── NAMESPACE
├── README.md
├── README.Rmd
├── man
│ └── my_function.Rd
├── R
│ └── my_function.R
├── tests
│ ├── testthat
│ │ └── test-my_function.R
│ └── testthat.R
└── vignettes
└── getting-started-with-my-function.Rmd
devtools
Tools to Make Developing R Packages Easier
Additional links
usethis
Automate Package and Project Setup
# Create a new package -------------------------------------------------
<- file.path(tempdir(), "mypkg")
path ::create_package(path)
usethis#> ✔ Creating '/tmp/Rtmp4VMzwK/mypkg/'
#> ✔ Setting active project to '/private/tmp/Rtmp4VMzwK/mypkg'
#> ✔ Creating 'R/'
#> ✔ Writing 'DESCRIPTION'
#> Package: mypkg
#> Title: What the Package Does (One Line, Title Case)
#> Version: 0.0.0.9000
#> Authors@R (parsed):
#> * First Last <first.last@example.com> [aut, cre] (YOUR-ORCID-ID)
#> Description: What the package does (one paragraph).
#> License: `use_mit_license()`, `use_gpl3_license()` or friends to pick a
#> license
#> Encoding: UTF-8
#> Roxygen: list(markdown = TRUE)
#> RoxygenNote: 7.2.0
#> ✔ Writing 'NAMESPACE'
#> ✔ Setting active project to '<no active project>'
# only needed since this session isn't interactive
::proj_activate(path)
usethis#> ✔ Setting active project to '/private/tmp/Rtmp4VMzwK/mypkg'
#> ✔ Changing working directory to '/tmp/Rtmp4VMzwK/mypkg/'
# Modify the description ----------------------------------------------
::use_mit_license("My Name")
usethis#> ✔ Setting License field in DESCRIPTION to 'AGPL (>= 3)'
#> ✔ Writing 'LICENSE.md'
#> ✔ Adding '^LICENSE\\.md$' to '.Rbuildignore'
::use_package("ggplot2", "Suggests")
usethis#> ✔ Adding 'ggplot2' to Suggests field in DESCRIPTION
#> • Use `requireNamespace("ggplot2", quietly = TRUE)` to test if package is installed
#> • Then directly refer to functions with `ggplot2::fun()`
# Set up other files -------------------------------------------------
::use_readme_md()
usethis#> ✔ Writing 'README.md'
#> • Update 'README.md' to include installation instructions.
::use_news_md()
usethis#> ✔ Writing 'NEWS.md'
::use_test("my-test")
usethis#> ✔ Adding 'testthat' to Suggests field in DESCRIPTION
#> ✔ Setting Config/testthat/edition field in DESCRIPTION to '3'
#> ✔ Creating 'tests/testthat/'
#> ✔ Writing 'tests/testthat.R'
#> ✔ Writing 'tests/testthat/test-my-test.R'
#> • Edit 'tests/testthat/test-my-test.R'
<- 1
x <- 2
y ::use_data(x, y)
usethis#> ✔ Adding 'R' to Depends field in DESCRIPTION
#> ✔ Creating 'data/'
#> ✔ Setting LazyData to 'true' in 'DESCRIPTION'
#> ✔ Saving 'x', 'y' to 'data/x.rda', 'data/y.rda'
#> • Document your data (see 'https://r-pkgs.org/data.html')
# Use git ------------------------------------------------------------
::use_git()
usethis#> ✔ Initialising Git repo
#> ✔ Adding '.Rproj.user', '.Rhistory', '.Rdata', '.httr-oauth', '.DS_Store' to '.gitignore'
Other
usethis::use_devtools()
usethis::use_build_ignore("<filename>")
to add files to.Rbuildignore
usethis::use_git_ignore("<filename>")
to add files to.gitignore
usethis::use_github_action()
orusethis::use_gitlab_ci()
to setup a CI (c.f.gitlabr
package below)
Additional links:
fusen
Build a Package from Rmarkdown Files
“
{fusen}
inflates a Rmarkdown file to magically create a package.”
<- file.path(getwd(), "examples", "my.fusen.pkg")
path ::create_fusen(path, template = "full", open = FALSE)
fusen#> ── Creating new directory: /path/to/examples/my.fusen.pkg ──────────────────────────────────────────────────────────────────────────────────────────────────
#> ✔ Creating '/path/to/examples/my.fusen.pkg/'
#> ✔ Setting active project to '/path/to/examples/my.fusen.pkg'
#> ✔ Creating 'R/'
#> ✔ Writing a sentinel file '.here'
#> • Build robust paths within your project via `here::here()`
#> • Learn more at <https://here.r-lib.org>
#> ✔ Setting active project to '<no active project>'
#> ✔ New directory created: /path/to/examples/my.fusen.pkg
#> ── Adding dev/flat_full.Rmd ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
#> File .here already exists in /path/to/examples/my.fusen.pkg
#> ✔ Added /path/to/examples/my.fusen.pkg/dev/flat_full.Rmd, /path/to/examples/my.fusen.pkg/dev/0-dev_history.Rmd
::add_flat_template(path, flat_name = "package")
fusen#> '0-dev_history.Rmd' already exists. It was not overwritten. Set `add_flat_template(overwrite = TRUE)` if you want to do so.
#> File .here already exists in /path/to/examples/my.fusen.pkg
#> • Modify '/path/to/examples/my.fusen.pkg/dev/flat_package.Rmd'
Package development
dev/(0-)dev_history.Rmd
: recipedev/flat_<flat_name1>.Rmd
,dev/flat_<flat_name2>.Rmd
, etc.: package content
Additional links
roxygen2
In-Line Documentation for R
File R/add.R
:
#' Add together two numbers
#'
#' @param x A number.
#' @param y A number.
#' @return A number.
#' @examples
#' add(1, 1)
#' add(10, 1)
<- function(x, y) {
add + y
x }
Automatic generation of man/add.Rd
with devtools::document()
:
% Generated by roxygen2: do not edit by hand
% Please edit documentation in ./<text>
\name{add}
\alias{add}
\title{Add together two numbers}
\usage{
add(x, y)
}
\arguments{
\item{x}{A number.}
\item{y}{A number.}
}
\value{
A number.
}
\description{
Add together two numbers
}
\examples{
add(1, 1)
add(10, 1)
}
Additional link
testthat
Unit Testing for R
# run once to configure the package meta-data
::use_testthat()
usethis# to create a test file "tests/testthat/test-my_function.R"
::use_test("my_function")
usethis#> ✔ Setting active project to '/home/drg/work/dev/R/funStatTest'
#> ✔ Writing 'tests/testthat/test-my_function.R'
#> • Modify 'tests/testthat/test-my_function.R'
File tests/testthat/test-my_function.R
:
test_that("multiplication works", {
expect_equal(2 * 2, 4)
})
Automatically run during package check (e.g. with devtools::check()
) or specifically with devtools::test()
.
checkmate
Fast and versatile argument checks for R
assert_xxx()
fails if assertion not mettest_xxx()
returns a the check result as a logical (TRUE
/FALSE
) valueexpect_xxx()
are designed to be used intestthat
unit tests.
::assert_choice("my-choice", choices = c("choice_1", "choice_2")) checkmate
Error in loadNamespace(x): there is no package called 'checkmate'
Example (source)
Standard input check: ::: {.cell}
<- function(n, method = "stirling") {
fact if (length(n) != 1)
stop("Argument 'n' must have length 1")
if (!is.numeric(n))
stop("Argument 'n' must be numeric")
if (is.na(n))
stop("Argument 'n' may not be NA")
if (is.double(n)) {
if (is.nan(n))
stop("Argument 'n' may not be NaN")
if (is.infinite(n))
stop("Argument 'n' must be finite")
if (abs(n - round(n, 0)) > sqrt(.Machine$double.eps))
stop("Argument 'n' must be an integerish value")
<- as.integer(n)
n
}if (n < 0)
stop("Argument 'n' must be >= 0")
if (length(method) != 1)
stop("Argument 'method' must have length 1")
if (!is.character(method) || !method %in% c("stirling", "factorial"))
stop("Argument 'method' must be either 'stirling' or 'factorial'")
if (method == "factorial")
factorial(n)
else
sqrt(2 * pi * n) * (n / exp(1))^n
}
:::
checkmate
-based input check: ::: {.cell}
<- function(n, method = "stirling") {
fact assertCount(n)
assertChoice(method, c("stirling", "factorial"))
if (method == "factorial")
factorial(n)
else
sqrt(2 * pi * n) * (n / exp(1))^n
}
:::
Advanced checks
<- runif(100)
x <- rnorm(100)
y # expect 100 numerical values with NA and between 0 and 1
::qassert(x, "N100[0,1]") checkmate
Error in loadNamespace(x): there is no package called 'checkmate'
::qassert(y, "N100[0,1]") checkmate
Error in loadNamespace(x): there is no package called 'checkmate'
Additional links
pkgdown
Build websites for R packages
# Run once to configure package to use pkgdown
::use_pkgdown() usethis
Config file: _pkgdown.yml
(see the https://pkgdown.r-lib.org/articles/customise.html)
# Run to build the website
::build_site() pkgdown
README.md
-> home pageindex.html
- vignettes -> “article” pages
man/*.Rd
-> “reference” pagesNEWS.md
-> “News” pagesDESCRIPTION
metadata file -> home page side bar with links and description
Additional links
And more
covr
: Test Coverage for Packages
::use_coverage()
usethis::package_coverage() covr
gitlabr
: Access to the ‘Gitlab’ API
Setup a Gitlab CI to check the package, check the test coverage and deploy a pkgdown
website as Gitlab pages:
::use_gitlab_ci(
gitlabrimage = "rocker/verse:latest",
type = "check-coverage-pkgdown"
)
lintr
: A Linter for R Code
::use_lintr(type = "tidyverse")
lintr::lint_package() lintr
withr
: Run Code With Temporarily Modified Global State
getwd()
#> [1] "/home/runner/work/withr/withr/docs/reference"
with_dir(tempdir(), {
# do some stuff
getwd()
})#> [1] "/tmp/RtmpR75In3"