6.1 KiB
6.1 KiB
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()andit()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:
- Self-sufficient tests - Each test contains all needed setup
- Self-contained tests - Use withr for automatic cleanup
- Plan for failure - Write tests that are easy to debug
- Repetition is OK - Clarity over DRY in tests
- 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
test_that("str_length() counts characters", {
expect_equal(str_length("abc"), 3)
expect_equal(str_length(""), 0)
})
BDD-Style Testing
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
test_that("error messages are helpful", {
expect_snapshot(error = TRUE, {
validate_input(NULL)
validate_input("wrong_type")
})
})
Testing with Fixtures
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
- R Packages: Testing Design
- R Packages: Testing Advanced
- testthat 3.0.0 release notes
- testthat 3.1 release notes
- testthat 3.2.0 release notes
- testthat 3.3.0 release notes
- testthat package documentation
Contributing
Found an issue or have a suggestion? Please open an issue or submit a pull request.
License
This skill is part of the Posit Claude Skills repository and is licensed under the MIT License.