
<!-- README.md is generated from README.Rmd. Please edit that file -->

# Doctest

<!-- badges: start -->

[![R-CMD-check](https://github.com/hughjonesd/doctest/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/hughjonesd/doctest/actions/workflows/R-CMD-check.yaml)
[![Lifecycle:
experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)
[![Codecov test
coverage](https://codecov.io/gh/hughjonesd/doctest/branch/master/graph/badge.svg)](https://app.codecov.io/gh/hughjonesd/doctest?branch=master)
![runiverse-package
badge](https://hughjonesd.r-universe.dev/badges/doctest) [![CRAN
status](https://www.r-pkg.org/badges/version/doctest)](https://CRAN.R-project.org/package=doctest)
<!-- badges: end -->

Documentation examples and tests are similar in some ways:

  - They are self-contained pieces of code.

  - They should cover the software’s most important functions and
    typical uses.

  - They should be simple and clear: complex examples are hard for users
    to understand, and complex test code can introduce testing bugs.

This similarity makes it attractive to use “doctests”, which combine
tests and documentation. Indeed, several languages, including Python and
Rust, have doctests built in.\[1\] R also checks for errors in examples
when running `R CMD check`.

The doctest package extends this idea. It lets you write
[testthat](https://testthat.r-lib.org/) tests, by adding tags to your
[roxygen](https://roxygen2.r-lib.org/) documentation. This helps you
check that your examples do what they are supposed to do.

## Example

Here’s some [roxygen](https://roxygen2.r-lib.org) documentation for a
function:

``` r

#' Fibonacci function 
#' 
#' @param n Integer
#' @return The nth Fibonacci number
#' 
#' @doctest
#'
#' @expect type("integer")
#' fib(2)
#'
#' n <- 6 
#' @expect equal(8)
#' fib(n)
#' 
#' @expect warning("not numeric")
#' fib("a")
#'
#' @expect warning("NA")
#' fib(NA)
fib <- function (n) {
  if (! is.numeric(n)) warning("n is not numeric")
  ...
}
```

Instead of an `@examples` section, we have a `@doctest` section.

This will create tests like:

    # Generated by doctest: do not edit by hand
    # Please edit file in R/<text>
    
    test_that("Doctest: fib", {
      # Created from @doctest for `fib`
      # Source file: <text>
      expect_type(fib(2), "integer")
      n <- 6
      expect_equal(fib(n), 8)
      expect_warning(fib("a"), "not numeric")
      expect_warning(fib(NA), "NA")
    })

The .Rd file will be created as normal, with an example section like:

    \examples{
    fib(2)
    
    n <- 6 
    fib(n)
    fib("a")
    fib(NA)
    }

## Usage

Install doctest from
[r-universe](https://r-universe.dev):

``` r
install.packages("doctest", repos = c("https://hughjonesd.r-universe.dev", 
                                      "https://cloud.r-project.org"))
```

Or from CRAN:

``` r
install.packages("doctest")
```

Or get the development version:

``` r
devtools::install("hughjonesd/doctest")
```

To use doctest in your package, alter its DESCRIPTION file to add the
`dt_roclet` roclet to roxygen:

``` r
Roxygen: list(roclets = c("collate", "rd", "namespace", 
              "doctest::dt_roclet")) 
```

Then use `roxygen2::roxygenize()` or `devtools::document()` to build
your package documentation.

For more information, see the [package
vignette](https://hughjonesd.github.io/doctest/articles/doctest.html).

1.  <https://docs.python.org/3/library/doctest.html>,
    <https://doc.rust-lang.org/rustdoc/write-documentation/documentation-tests.html>
