Skip to content

Conversation

@hadley
Copy link
Member

@hadley hadley commented Nov 5, 2025

First draft

Copy link
Member

@lionel- lionel- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice release!


Overall it was a successful experiment. It helped me close over 100 issues in what felt like less time than usual. I don't have any hard numbers, but my gut feeling is that it was maybe a 10-20% improvement to my development velocity. This is still significant, especially since I'm an experienced R programmer and my workflow has been pretty stable for the last few years. I mostly used Claude for smaller, well-defined tasks where I had a good sense of what was needed. I found it particularly useful for refactoring, where it was easy to say precisely what I wanted, but executing the changes required a bunch of fiddly edits across many files.

I also found it generally useful for getting over the "activation energy hump": there were a few issues that had been stagnating for years because they felt like they were going to be hard to do and with relatively limited payoff. I let Claude Code loose on a few of these and found it super useful. It only produced code I was really happy with a couple of times, but every time it gave me something to react to (often with strong negative feelings!) and that got me started actually engaging with the problem.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anger-driven engagement algorithm for coders


## Other new features

* testthat generally does a better job of handling nested tests, aka subtests, where you put a `test_that()` inside another `test_that()`, or more typically `it()` inside of `describe()`. Subtests will now generate more informative failure messages, free from duplication, with more informative skips if any subtests don't contain any expectations.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought nesting test_that() was mostly useful for testing the testthat package with itself, but this paragraph makes it sound like there might be user-oriented cases where this is helpful? If that's the case, it might be interesting to add a sentence explaining the use case, otherwise a sentence explaining this is mostly for internal testing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's mostly about making it possible to write tests inside of functions that get called inside of other tests. This is sometimes useful when you want to test that multiple functions/classes adhere to the same interface. But I'm also not 100% convinced that it's the right approach, so I don't want to go into the details here.


* `vignette("mocking")` explains mocking in detail, and new `local_mocked_s3_method()`, `local_mocked_s4_method()`, and `local_mocked_r6_class()` make it easier to mock S3 and S4 methods and R6 classes.

* `test_dir()`, `test_check()`, and friends gain a `shuffle` argument that uses `sample()` to randomly reorder the top-level expressions in each test file. This random reordering surfaces dependencies between tests and code outside of any test, as well as dependencies between tests, helping you find and eliminate unintentional dependencies.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's nice


* `test_dir()`, `test_check()`, and friends gain a `shuffle` argument that uses `sample()` to randomly reorder the top-level expressions in each test file. This random reordering surfaces dependencies between tests and code outside of any test, as well as dependencies between tests, helping you find and eliminate unintentional dependencies.

* `try_again()` is now publicized, as it's a useful tool for testing flaky code:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, might be worth a note that this should still be skipped on CRAN? And include a skip_on_cran() in the example.

* New `SlowReporter` makes it easier to find the slowest tests in your package. You can run it with `devtools::test(reporter = "slow")`.

* New `vignette("challenging-functions")` provides an index to other documentation organized by various challenges.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use the new features, do you recommend bumping the version of testthat in Suggests? Might be a good place to mention it.

Unfortunately pkgload only checks for Imports not Suggests, so bumping the dep won't trigger the install prompt on load.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, and install.packages() won't check for it either. So overall, I don't think it's worth it.

Copy link
Contributor

@teunbrand teunbrand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes me excited to try out the new features!

@hfrick
Copy link
Member

hfrick commented Nov 11, 2025

So many cool changes!

Sidenote: My local preview, opened in Firefox, has the horizontal line in the test_that() output piercing out to the right.
Screenshot 2025-11-11 at 16 08 46

@hadley
Copy link
Member Author

hadley commented Nov 11, 2025

@hfrick thanks for spotting. fixed now!

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

Successfully merging this pull request may close these issues.

5 participants