| name | r-package-development |
| description | R package dev with devtools, testthat, and roxygen2. |
| user-invocable | true |
| allowed-tools | ["Read","Edit","Write","Bash"] |
| metadata | {"author":"Simon P. Couch (@simonpcouch)","version":"1.2"} |
R package development
Key commands
# Run code in the package
Rscript -e "devtools::load_all(); code"
# Run all tests
Rscript -e "devtools::test()"
# Run all tests for files starting with {name}
Rscript -e "devtools::test(filter = '^{name}')"
# Run all tests for R/{name}.R
Rscript -e "devtools::test_active_file('R/{name}.R')"
# Run a single test "blah" for R/{name}.R
Rscript -e "devtools::test_active_file('R/{name}.R', desc = 'blah')"
# Redocument the package
Rscript -e "devtools::document()"
# Check pkgdown documentation
Rscript -e "pkgdown::check_pkgdown()"
# Check the package with R CMD check
Rscript -e "devtools::check()"
# Format code
air format .
Coding
- Always run
air format . after generating code.
- Use the base pipe operator (
|>) not the magrittr pipe (%>%).
- Use
\() ... for single-line anonymous functions.
For all other cases, use function() {...}.
Testing
For the full testthat API (fixtures, mocking, snapshots, BDD-style tests), see testing-r-packages.
Match the package's existing expect_error()/expect_warning() or snapshot-testing style where precedent exists.
On a fresh package with no precedent, follow testing-r-packages' preference for snapshot-based error/warning tests.
- Tests for
R/{name}.R go in tests/testthat/test-{name}.R.
- All new code should have an accompanying test.
- If there are existing tests, place new tests next to similar existing tests.
- Strive to keep tests minimal with few comments.
- Avoid
expect_true() and expect_false() in favour of a specific expectation which will give a better failure message.
- When testing errors and warnings, match the package's existing precedent where one exists (see above).
On a fresh package with no precedent, use
expect_snapshot(error = TRUE) for errors and expect_snapshot() for warnings, not expect_error() or expect_warning().
A snapshot lets the user review the full text of the output.
Documentation
- Every user-facing function should be exported and have roxygen2 documentation.
- Wrap roxygen comments at 80 characters.
- Internal functions should not have roxygen documentation.
- Whenever you add a new (non-internal) documentation topic, also add the topic to
_pkgdown.yml.
- Always re-document the package after changing a roxygen2 comment.
- Use
pkgdown::check_pkgdown() to check that all topics are included in the reference index.
NEWS.md
This is the tidyverse-style default.
When the package already has an established NEWS.md style, match that existing style instead --- see r-pkg-news, whose whole job is reading a package's precedent before drafting a new entry.
- Every user-facing change should be given a bullet in
NEWS.md.
Do not add bullets for small documentation changes or internal refactorings.
- Each bullet should briefly describe the change to the end user.
- If the change is related to a function, put the name of the function early in the bullet.
- If the bullet is related to a GitHub issue or pull request, reference it by number in parentheses before the final period:
(#123)..
- Order bullets alphabetically by function name.
Put all bullets that don't mention function names at the beginning.
Relationship to other skills
This skill is a day-to-day dev-loop reference (load, test, document, format) with this author's own conventions.
It does not replace, and does not cover:
r-pkg-check --- running and triaging devtools::check() output.
r-pkg-cran-checklist --- the CRAN release mechanics (win-builder, revdep checks, devtools::release()).
cran-extrachecks --- the ad-hoc/stylistic CRAN checklist (Title case, @return tags, URL hygiene) that devtools::check() doesn't catch on its own.
r-pkg-news --- matching a package's existing NEWS.md style, which overrides this skill's own default above.
testing-r-packages --- the full testthat API (fixtures, mocking, snapshots, BDD-style tests).
Match the package's existing expect_error()/expect_warning() or snapshot-testing style where precedent exists.
On a fresh package with no precedent, follow testing-r-packages' preference for snapshot-based error/warning tests, which agrees with this skill's own default above.