Initial commit
This commit is contained in:
199
skills/testing-r-packages/README.md
Normal file
199
skills/testing-r-packages/README.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# Testing R Packages
|
||||
|
||||
Best practices for writing R package tests using testthat version 3+.
|
||||
|
||||
## Overview
|
||||
|
||||
This skill provides comprehensive guidance on modern R package testing with testthat 3, including:
|
||||
|
||||
- **Test structure and organization** - File organization, test hierarchy, and naming conventions
|
||||
- **Core expectations** - All testthat expectation functions for equality, errors, types, and more
|
||||
- **Design principles** - Self-sufficient tests, cleanup with withr, and test-first workflows
|
||||
- **Snapshot testing** - Testing complex output, error messages, and visual diffs
|
||||
- **Test fixtures** - Constructor functions, static files, and helper organization
|
||||
- **Mocking** - Replacing external dependencies for reliable testing
|
||||
- **BDD-style testing** - Using `describe()` and `it()` for behavior-driven development
|
||||
- **Advanced topics** - Skipping tests, managing secrets, CRAN requirements, and parallel testing
|
||||
|
||||
## When This Skill Activates
|
||||
|
||||
Claude will use this skill when you:
|
||||
|
||||
- Write or modify tests for R packages
|
||||
- Set up testing infrastructure with testthat
|
||||
- Debug failing tests
|
||||
- Organize test files and fixtures
|
||||
- Create snapshot tests for complex output
|
||||
- Mock external dependencies
|
||||
- Follow BDD patterns with describe/it
|
||||
- Prepare packages for CRAN submission
|
||||
|
||||
## What You'll Learn
|
||||
|
||||
### Test Structure
|
||||
|
||||
Learn the modern testthat 3 workflow:
|
||||
- Initializing testing with `usethis::use_testthat(3)`
|
||||
- Organizing tests to mirror package structure
|
||||
- Using helper and setup files
|
||||
- Running tests at different scales
|
||||
|
||||
### Expectations
|
||||
|
||||
Master all core expectations:
|
||||
- Equality: `expect_equal()`, `expect_identical()`, `expect_all_equal()`
|
||||
- Errors: `expect_error()`, `expect_no_error()`, `expect_warning()`
|
||||
- Types: `expect_type()`, `expect_s3_class()`, `expect_r6_class()`
|
||||
- Structure: `expect_length()`, `expect_shape()`, `expect_named()`
|
||||
- Sets: `expect_contains()`, `expect_in()`, `expect_disjoint()`
|
||||
|
||||
### Design Principles
|
||||
|
||||
Follow five key principles:
|
||||
1. **Self-sufficient tests** - Each test contains all needed setup
|
||||
2. **Self-contained tests** - Use withr for automatic cleanup
|
||||
3. **Plan for failure** - Write tests that are easy to debug
|
||||
4. **Repetition is OK** - Clarity over DRY in tests
|
||||
5. **devtools::load_all() workflow** - Efficient interactive testing
|
||||
|
||||
### Snapshot Testing
|
||||
|
||||
Test complex output effectively:
|
||||
- Capture printed output, messages, and errors
|
||||
- Use transforms to remove variable elements
|
||||
- Create platform-specific variants
|
||||
- Review and accept snapshot changes
|
||||
|
||||
### BDD-Style Testing
|
||||
|
||||
Write specification-style tests:
|
||||
- Group related specs with `describe()`
|
||||
- Define individual specs with `it()`
|
||||
- Create nested hierarchies
|
||||
- Mark pending specs without code
|
||||
- Follow test-first development
|
||||
|
||||
## File Organization
|
||||
|
||||
The skill uses progressive disclosure with reference files:
|
||||
|
||||
```
|
||||
testing-r-packages/
|
||||
├── SKILL.md # Core workflows and common patterns
|
||||
└── references/
|
||||
├── bdd.md # BDD-style testing with describe/it
|
||||
├── snapshots.md # Comprehensive snapshot testing
|
||||
├── mocking.md # Mocking strategies and patterns
|
||||
├── fixtures.md # Test data management
|
||||
└── advanced.md # Advanced topics and edge cases
|
||||
```
|
||||
|
||||
Core guidance loads automatically, while reference files load only when needed for specific scenarios.
|
||||
|
||||
## Key Features
|
||||
|
||||
### Modern testthat 3 Patterns
|
||||
|
||||
- Edition system with `Config/testthat/edition: 3`
|
||||
- Improved snapshot testing
|
||||
- Better error messages with waldo
|
||||
- New expectations (`expect_no_error()`, `expect_contains()`, etc.)
|
||||
- `local_mocked_bindings()` for reliable mocking
|
||||
- Parallel test execution support
|
||||
|
||||
### Comprehensive Coverage
|
||||
|
||||
- Basic to advanced testing techniques
|
||||
- Real-world examples from tidyverse packages
|
||||
- Common patterns and anti-patterns
|
||||
- Platform and CRAN considerations
|
||||
- Integration with withr, waldo, and related packages
|
||||
|
||||
### Best Practices
|
||||
|
||||
- Test-first development workflows
|
||||
- Proper fixture management
|
||||
- Secrets and credentials handling
|
||||
- File system discipline
|
||||
- Custom expectations and helpers
|
||||
|
||||
## Examples
|
||||
|
||||
### Standard Testing
|
||||
|
||||
```r
|
||||
test_that("str_length() counts characters", {
|
||||
expect_equal(str_length("abc"), 3)
|
||||
expect_equal(str_length(""), 0)
|
||||
})
|
||||
```
|
||||
|
||||
### BDD-Style Testing
|
||||
|
||||
```r
|
||||
describe("User authentication", {
|
||||
describe("login()", {
|
||||
it("accepts valid credentials", {
|
||||
result <- login("user@example.com", "password123")
|
||||
expect_true(result$authenticated)
|
||||
})
|
||||
|
||||
it("rejects invalid credentials", {
|
||||
expect_error(login("user@example.com", "wrong"), class = "auth_error")
|
||||
})
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Snapshot Testing
|
||||
|
||||
```r
|
||||
test_that("error messages are helpful", {
|
||||
expect_snapshot(error = TRUE, {
|
||||
validate_input(NULL)
|
||||
validate_input("wrong_type")
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Testing with Fixtures
|
||||
|
||||
```r
|
||||
test_that("processes CSV files", {
|
||||
csv_path <- test_path("fixtures", "sample.csv")
|
||||
result <- process_csv(csv_path)
|
||||
expect_equal(nrow(result), 100)
|
||||
})
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- R package with tests initialized via `usethis::use_testthat(3)`
|
||||
- testthat version 3.0.0 or later
|
||||
- R 4.1+ for latest testthat features
|
||||
|
||||
## Related Skills
|
||||
|
||||
- **package-development** - General R package development workflows
|
||||
- **debugging** - Debugging R code and tests
|
||||
- **documentation** - Writing package documentation
|
||||
|
||||
## Resources
|
||||
|
||||
This skill synthesizes guidance from:
|
||||
- [R Packages: Testing Basics](https://r-pkgs.org/testing-basics.html)
|
||||
- [R Packages: Testing Design](https://r-pkgs.org/testing-design.html)
|
||||
- [R Packages: Testing Advanced](https://r-pkgs.org/testing-advanced.html)
|
||||
- [testthat 3.0.0 release notes](https://tidyverse.org/blog/2020/10/testthat-3-0-0/)
|
||||
- [testthat 3.1 release notes](https://tidyverse.org/blog/2021/10/testthat-3-1/)
|
||||
- [testthat 3.2.0 release notes](https://tidyverse.org/blog/2023/10/testthat-3-2-0/)
|
||||
- [testthat 3.3.0 release notes](https://tidyverse.org/blog/2025/11/testthat-3-3-0/)
|
||||
- testthat package documentation
|
||||
|
||||
## Contributing
|
||||
|
||||
Found an issue or have a suggestion? Please [open an issue](https://github.com/posit-dev/skills/issues) or submit a pull request.
|
||||
|
||||
## License
|
||||
|
||||
This skill is part of the [Posit Claude Skills](https://github.com/posit-dev/skills) repository and is licensed under the MIT License.
|
||||
Reference in New Issue
Block a user