Documentation and Style
Use one convention from the first function. Code that is easy to read is easier to test, review, and publish.
For R packages in these guides, use the Google R Style Guide,
write API documentation with roxygen2, and put unit tests
in testthat.
The project contract
Section titled “The project contract”Use BigCamelCase for public functions, snake_case for local objects, and an initial
dot for private functions. Use <- for assignment, never right hand assignment. Return
the value explicitly. Qualify functions from non base packages with package::function().
#' Calculates counts per million.#'#' @param counts A numeric vector of nonnegative read counts.#' @return A numeric vector scaled to one million reads.#' @examples#' CountsPerMillion(c(25, 75))#' @exportCountsPerMillion <- function(counts) { stopifnot( "counts must be numeric" = is.numeric(counts), "counts must not contain NA" = !anyNA(counts), "counts must not be negative" = all(counts >= 0), "counts must have a positive total" = sum(counts) > 0 )
return(counts / sum(counts) * 1e6)}The #' lines belong directly above the function they describe. They are not ordinary
comments. They are roxygen2 tags that generate the help page and the exported name.
Generate package documentation with roxygen2
Section titled “Generate package documentation with roxygen2”Start a package once. Add testthat and roxygen2 as development dependencies, then let
the package tools create the expected directory structure.
usethis::create_package("geneTools")usethis::use_testthat(edition = 3)usethis::use_roxygen_md()Place source files in R/. Run this after adding or changing a roxygen block:
devtools::document()It creates or updates the .Rd help files in man/ and the NAMESPACE. Do not edit
either generated file by hand. Change the roxygen block and run devtools::document()
again.
Use @param for every public argument, @return for every public result, and
@examples for a small call that runs without private data or network access. Add
@export only when callers should use the function. For a dependency, put
@importFrom package function above the function that uses it. This keeps the dependency
visible at the point of use.
Tests sit beside the package source
Section titled “Tests sit beside the package source”testthat is the unit testing standard for R in this project. Keep a test file for each
public behavior under tests/testthat/.
geneTools/ R/ counts.R tests/ testthat/ test-counts.R man/ # generated by roxygen2 DESCRIPTION NAMESPACE # generated by roxygen2test_that("CountsPerMillion preserves a total of one million", { output <- CountsPerMillion(c(25, 75))
expect_equal(sum(output), 1e6) expect_equal(output, c(250000, 750000))})Run the suite during development with devtools::test(). Run devtools::check() before
a release. The Testing and Assertions lesson covers
known answers, invariants, edge cases, and deterministic random tests.
Documentation checklist
Section titled “Documentation checklist”Before merging a public R function, check the following:
| Check | Required action |
|---|---|
| Name | Use BigCamelCase for public functions. |
| Inputs | Validate assumptions and document each argument with @param. |
| Result | State the returned type and meaning with @return. |
| Dependencies | Use package::function() and the matching @importFrom tag. |
| Example | Include a small, executable @examples call. |
| Tests | Add a testthat test for the public behavior. |
| Generated files | Run devtools::document() and commit the changed man/ and NAMESPACE files. |
Next steps
Section titled “Next steps”Read Testing and Assertions for the test suite that protects this documented API. The roxygen2 reference lists the available tags and package documentation patterns.