Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

offer idiom to reuse fixture / setup code in vignettes, examples, docs #1308

Closed
maxheld83 opened this issue Jan 25, 2021 · 1 comment
Closed

Comments

@maxheld83
Copy link
Member

maxheld83 commented Jan 25, 2021

I like to reuse the fixture / setup code I use (and test) in testthat across other places in the package, such as vignettes, example, docs.

This might be best explained with an example (pseudocode):

Say, I have a tests/testthat/test-foo.R:

test_that("foofy can add two numbers", {
  out <- source(test_path(foofy.R))
  expect_equal(out, 2)
})

The setup / example code lives in tests/testthat/foofy.R:

foofy(1, 1)

I then reuse this in the roxygen2 documentation with the @example "tests/testthat/foofy.R tag, as well as in a vignette with a knitr child = "../tests/testthat/foofy.R document.
Obviously, the code in tests/testthat/foofy.R would be longer; typically for setting up some data structure.

I like this because:

  1. It can reduce code duplication somewhat (see this PR in roxygen, for example)
  2. It makes it easier to change things.
  3. It gets me some way to a Design-by-Contract (DbC) paradigm, where I make sure that everything I promise the users in the vignette and the examples is actually also tested.
  4. It makes me provide more, better tests and examples, because I only have to go through the pain once.

This works fine, and there's not necessarily any technical aspect missing, but the above practice:

  1. Deposits information that belongs together in yet more files.
  2. There can be quite a lot of tests/testthat/foofy.R-type files.
  3. The long relative paths can be somewhat disorienting.

In other words: The whole thing isn't very idiomatic, and can easily make life harder for collaborators, because they have another thing to figure out.

It would be nice to have some canonical way to do this.

I'm not sure what the answer to this is, or if testthat would even be the right place.

Some preliminary ideas:

  • Maybe just extending test_path() with a new friend or feature, to also find paths from inside vignettes and pkg root (for roxygen2 #' @example).
  • Maybe recommend a different directory for where these setup pieces / examples should be stored?

Happy to start a PR on this if there's some interest and guidance.

@hadley
Copy link
Member

hadley commented Jan 25, 2021

I like this principle:

Good production code is well-factored; good test code is obvious.

from https://mtlynch.io/good-developers-bad-tests/

I think copy-and-paste duplication in tests is actually a good thing, because when a test fails, you want the thinnest possible layer between you and the broken code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants