---
description: Rails Testing Guide
applyTo: "test/**/*_test.rb"
---

# Rails Testing Guide

## Core Philosophy

- Test-Driven Development (TDD) as default practice
- Use Minitest and fixtures, not RSpec or factories
- Test behavior, not implementation details
- Keep tests fast, focused, and reliable
- Write tests that serve as documentation

## Testing Principles

- Write tests first, then implementation
- One assertion per test when possible
- Test the happy path and edge cases
- Keep test data realistic and minimal
- Make tests independent and repeatable

## Test Organization

- Mirror app structure in test directory
- Group related tests in the same file
- Use descriptive test names
- Keep test files focused and manageable
- Organize tests by feature or behavior

## Fixtures Best Practices

- Use fixtures for test data, not factories
- Keep fixtures simple and realistic
- Reference fixtures by meaningful names
- Share fixtures across related tests
- Update fixtures when models change

## Model Testing

- Test all validations thoroughly
- Verify associations work correctly
- Test scopes with various data sets
- Check business logic and calculations
- Ensure callbacks behave properly

## Controller Testing

- Focus on HTTP concerns only
- Test authentication and authorization
- Verify response formats and status codes
- Check parameter filtering
- Test error handling scenarios

## System Testing

- Test complete user workflows
- Use Capybara for browser automation
- Test JavaScript interactions
- Verify Turbo Frame updates
- Check responsive behavior

## Service Object Testing

- Test services in complete isolation
- Mock external dependencies
- Verify success and failure paths
- Test edge cases and error conditions
- Ensure proper transaction handling

## Integration Testing

- Test API endpoints thoroughly
- Verify request/response cycles
- Test authentication flows
- Check cross-controller workflows
- Validate data consistency

## Test Data Management

- Keep test data minimal and focused
- Use fixtures for common scenarios
- Create data in tests for specific cases
- Clean up after tests when needed
- Avoid test data dependencies

## Mocking and Stubbing

- Mock external services only
- Avoid mocking your own objects
- Use stubs for time-dependent code
- Keep mocks simple and obvious
- Document why mocking is necessary

## Test Performance

- Keep individual tests under 1 second
- Use parallel testing for speed
- Profile slow tests regularly
- Optimize database operations
- Cache expensive test setup

## Test Coverage

- Aim for high coverage without obsessing
- Focus on critical business logic
- Test error paths thoroughly
- Don't test framework code
- Use coverage as a guide, not a goal

## Continuous Integration

- Run tests on every commit
- Keep CI builds fast
- Fix broken tests immediately
- Test multiple Ruby versions
- Monitor test reliability

## Test Helpers

- Create helpers for common test patterns
- Keep helpers focused and reusable
- Document helper methods clearly
- Share helpers across test types
- Avoid complex helper logic

## Testing JavaScript

- Use system tests for JavaScript behavior
- Test Stimulus controllers thoroughly
- Verify Turbo interactions work
- Check progressive enhancement
- Test without JavaScript enabled

## API Testing

- Test all endpoints and methods
- Verify authentication requirements
- Check response formats and schemas
- Test rate limiting and throttling
- Validate error responses

## Background Job Testing

- Test job logic separately from queuing
- Verify job parameters and execution
- Test retry and failure scenarios
- Check job side effects
- Ensure idempotency

## Email Testing

- Test email delivery and content
- Verify recipient and sender details
- Check email templates render correctly
- Test attachments and multipart emails
- Validate email queueing

## Security Testing

- Test authorization for all actions
- Verify parameter filtering works
- Check for SQL injection vulnerabilities
- Test CSRF protection
- Validate input sanitization

## Performance Testing

- Profile critical code paths
- Test with realistic data volumes
- Monitor query counts
- Check memory usage
- Benchmark important operations

## Test Maintenance

- Refactor tests alongside code
- Remove obsolete tests promptly
- Keep tests DRY but readable
- Update tests when requirements change
- Review test quality regularly

## Common Anti-Patterns

- Testing implementation instead of behavior
- Overly complex test setup
- Brittle tests dependent on order
- Testing framework functionality
- Slow test suites that discourage TDD

## Debugging Tests

- Use byebug for test debugging
- Add descriptive failure messages
- Check test logs for details
- Isolate failing tests
- Verify test environment setup

## Best Practices Summary

- Write tests first
- Keep tests simple and fast
- Use fixtures over factories
- Test behavior, not implementation
- Maintain tests like production code

Remember: Tests are your safety net and documentation. Write them first, keep them simple, and maintain them well.
