You’re building a great Rails app, but that nagging voice remains: “I should be writing more tests…” We’ve all been there. Between tight deadlines and the pressure to ship features, comprehensive test coverage often takes a back seat. The result? Those late-night debugging sessions when production mysteriously breaks. Well, you need Rails Unit Test!
CodeBeaver is an AI-powered testing assistant that automatically generates and maintains unit tests for your Rails application. It works by analyzing your code, understanding its purpose, and writing tests that verify its behavior—all while following Rails conventions. When you open a pull request, CodeBeaver jumps into action, generating tests for your changes and opening a PR with the new tests for you to review.
Unlike generic AI solutions that might not understand Rails idioms, CodeBeaver generates tests that respect ActiveRecord relationships, Rails validations, and the Test-Driven Development philosophy that’s been part of Rails since its inception. It’s like having a testing expert on your team who works 24/7 and never forgets an edge case.
This tutorial is for Rails developers who:
- Already have a Rails application but struggle to maintain test coverage
- Want to catch regressions before they reach production
- Need to improve test coverage without spending hours writing boilerplate tests
- Prefer to focus on building features rather than manually maintaining test suites
In the next 15 minutes, you’ll learn how to set up CodeBeaver for your Rails project and start generating comprehensive tests automatically. Let’s dive in!
Prerequisites
Before setting up CodeBeaver for your Rails project, ensure you have:
- A Rails application (Rails 5.0 or higher recommended)
- Git repository hosted on GitHub, GitLab, or Bitbucket
- Basic familiarity with either RSpec or Minitest
- Ability to run your application’s test suite locally
- Admin access to your repository for CodeBeaver integration
Your Rails project should follow standard structure conventions, but don’t worry if your testing setup isn’t perfect yet—that’s exactly what we’re here to improve. If you’re using a non-standard directory structure or custom test runners, you may need to create a more detailed configuration later.
If you’re working with a monorepo or have your Rails application in a subdirectory, make note of the path as you’ll need it when configuring CodeBeaver.
Setting Up Your Rails Project for Testing
Before connecting your Rails application to CodeBeaver, you’ll want to ensure it has a solid foundation for testing. This foundation will make CodeBeaver’s automated test generation more effective.
RSpec vs Minitest: Choose Your Framework
Rails ships with Minitest by default, but many developers prefer RSpec for its expressive syntax:
# Minitest (built-in)
def test_user_is_valid
user = User.new(name: "Test", email: "test@example.com")
assert user.valid?
end
# RSpec (requires gem)
it "is valid with name and email" do
user = User.new(name: "Test", email: "test@example.com")
expect(user).to be_valid
end
CodeBeaver works equally well with both frameworks. If your project already uses one, stick with it. For new projects, add RSpec with:
# Gemfile
group :development, :test do
gem 'rspec-rails'
end
Then run rails generate rspec:install
to set up the necessary files.
Essential Testing Gems for Rails Unit Test
Add these powerful testing tools to your Gemfile. They are helpful when setting up your Rails Unit Test pipeline:
group :development, :test do
gem 'rspec-rails' # If using RSpec
gem 'factory_bot_rails' # For test data factories
gem 'faker' # For generating realistic test data
gem 'shoulda-matchers' # One-liners for common Rails validations
end
group :test do
gem 'database_cleaner-active_record' # Keeps test database clean
gem 'simplecov' # For test coverage metrics
end
Configuring Your Test Database
Rails comes with a pre-configured test database, but ensure your database.yml
is properly set up:
test:
adapter: postgresql
database: your_app_test
host: localhost
username: postgres
password: password
For CodeBeaver, we’ll later configure a containerized database so you don’t need to worry about local conflicts.
Creating a Strong Directory Structure
For larger applications, organize your test files to mirror your application structure:
spec/
├── models/
├── controllers/
├── requests/
├── services/
├── factories/
├── support/
│ ├── database_cleaner.rb
│ ├── factory_bot.rb
│ └── shoulda_matchers.rb
└── rails_helper.rb
This structure makes it easier for CodeBeaver to understand your project’s organization and generate appropriate tests.
With this foundation in place, you’re ready to connect your Rails project to CodeBeaver and start generating comprehensive tests automatically.
Connecting Your Rails Repository to CodeBeaver
Now, let’s connect your Rails repository to CodeBeaver:
- Navigate to codebeaver.ai and select “Sign up with GitHub” (or GitLab/Bitbucket, depending on where you hosted your repository)
- Authorize CodeBeaver to access your repositories when prompted

After authenticating, you’ll need to give CodeBeaver permission to access your repositories:

Click “Install CodeBeaver” to proceed. You can choose to give access to all repositories or just specific ones. Don’t worry about getting the permissions exactly right—you can always modify these settings later.
You will now be able to set up some options related to Rails Unit Test. After that, CodeBeaver will analyze your repository and try to auto-configure itself. If your Rails project needs a DB for testing – as most do – you will need some additional configuration, explained in the next section.

Configuring CodeBeaver for Rails Projects
For CodeBeaver to effectively generate tests for your Rails application, you’ll need to configure it to understand your specific Rails environment. The codebeaver.yml
file is the key to this configuration.
Creating the codebeaver.yml
File for Rails
Create a new file called codebeaver.yml
in the root of your repository. This file tells CodeBeaver how to run your Rails tests.
You can start with a template configuration, using the built-in Ruby template:
from: ruby
While this basic configuration works for simple Ruby projects, Rails applications typically require additional setup for databases and other services.
Setting Up the Proper Database Configuration
Rails applications usually need a database for testing. Here’s how to configure PostgreSQL, the most common database for Rails applications:
from: ruby
services:
ruby:
image: ruby:3.1-slim
depends_on:
- db
environment:
DATABASE_URL: postgres://postgres:password@db:5432/your_app_test
RAILS_ENV: test
db:
image: postgres:14
environment:
POSTGRES_PASSWORD: password
POSTGRES_USER: postgres
POSTGRES_DB: your_app_test
volumes:
- postgres_data:/var/lib/postgresql/data
This configuration:
- Uses the Ruby template as a base
- Sets up a PostgreSQL database service
- Configures the Ruby service to connect to the database
- Sets the Rails environment to
test
If you’re using MySQL instead, adjust your configuration like this:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: your_app_test
volumes:
- mysql_data:/var/lib/mysql
And update your DATABASE_URL
accordingly:
environment:
DATABASE_URL: mysql2://root:password@db:3306/your_app_test
Configuring Additional Services
Many Rails applications rely on additional services like Redis for caching or Elasticsearch for search. You can add these services to your configuration:
services:
# Your ruby and db services here...
redis:
image: redis:7.0
volumes:
- redis_data:/data
elasticsearch:
image: elasticsearch:7.17.9
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
Then update your Ruby service to depend on these additional services:
ruby:
# Existing configuration...
depends_on:
- db
- redis
- elasticsearch
environment:
# Existing environment variables...
REDIS_URL: redis://redis:6379/0
ELASTICSEARCH_URL: http://elasticsearch:9200
Environment Variables and Rails-Specific Settings (Optional)
Rails applications often require specific environment variables for testing. Add these to your Ruby service’s environment settings:
environment:
RAILS_ENV: test
DATABASE_URL: postgres://postgres:password@db:5432/your_app_test
RAILS_MASTER_KEY: your_master_key_for_tests # Optional: for decrypting credentials
DISABLE_SPRING: true # Recommended for testing
RAILS_LOG_TO_STDOUT: true
For test-specific settings, you can also add setup commands that run before the tests:
setup_commands:
- bundle install
- bundle exec rails db:test:prepare
- bundle exec rails assets:precompile # If using asset pipeline
Testing and Coverage Commands for Rails
Finally, configure the commands that CodeBeaver should use to run your tests and measure coverage:
test_commands:
- bundle exec rspec
single_file_test_commands:
- bundle exec rspec $TEST_FILE
# If using SimpleCov for coverage
test_commands:
- COVERAGE=true bundle exec rspec
- bundle exec simplecov-json
If you’re using Minitest instead of RSpec, adjust your commands to reflect this Rails Unit Test setting:
test_commands:
- bundle exec rails test
single_file_test_commands:
- bundle exec rails test $TEST_FILE
Complete Configuration Example for Rails Unit Test
Here’s a complete example for a typical Rails application using PostgreSQL, Redis, and RSpec:
from: ruby
services:
ruby:
image: ruby:3.1-slim
depends_on:
- db
- redis
environment:
DATABASE_URL: postgres://postgres:password@db:5432/your_app_test
REDIS_URL: redis://redis:6379/0
RAILS_ENV: test
DISABLE_SPRING: true
RAILS_LOG_TO_STDOUT: true
db:
image: postgres:14
environment:
POSTGRES_PASSWORD: password
POSTGRES_USER: postgres
POSTGRES_DB: your_app_test
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7.0
volumes:
- redis_data:/data
setup_commands:
- apt-get update && apt-get install -y nodejs
- bundle install
- bundle exec rails db:test:prepare
test_commands:
- COVERAGE=true bundle exec rspec
- bundle exec simplecov-json
single_file_test_commands:
- COVERAGE=true bundle exec rspec $TEST_FILE
- bundle exec simplecov-json
This configuration provides CodeBeaver with everything it needs to run your Rails tests in an isolated environment that mirrors your production setup.
Commit this file to the root of your repository, and CodeBeaver will use it to generate and run tests for your Rails application on your next pull request.
Trying out your Rails Unit Tests!
Now that you’ve set up CodeBeaver for your Rails project, let’s see it in action. The process is straightforward:
- Create a pull request with your changes. For example, add a new model or controller, or modify an existing one.
- Watch CodeBeaver work. CodeBeaver will analyze your changes, run your test suite, and determine what tests need to be written. You’ll see a GitHub check (or equivalent on GitLab/Bitbucket) indicating that CodeBeaver is processing your PR.
- Review the generated tests. Within a few minutes, CodeBeaver will open a new PR against your original PR, containing test files for your changes. These tests will follow your project’s conventions and test both happy paths and edge cases.
- Merge the CodeBeaver PR. After reviewing the tests, you can merge CodeBeaver’s PR into your feature branch. This updates your original PR with the necessary tests before it’s merged into your main branch.
That’s it! With minimal effort, you’ve maintained comprehensive test coverage for your Rails application. CodeBeaver will continue to help maintain your test suite as your codebase evolves.
Best Practices for Rails Unit Tests with CodeBeaver
While conventional testing best practices apply when working with CodeBeaver, there are specific approaches that significantly enhance CodeBeaver’s ability to generate effective tests for your Rails application. Since CodeBeaver analyzes your code to understand its purpose and behavior, the way you structure and document your code directly impacts the quality of the generated tests.
Clearly Describing Function Purpose for CodeBeaver
The single most important practice for effective CodeBeaver test generation is clearly describing what each function is supposed to do. Unlike human developers who might infer intent from context, CodeBeaver relies heavily on explicit descriptions.
1. Use Descriptive Method Comments with Expected Behaviors
CodeBeaver excels when it can understand the exact purpose and expected behavior of your methods:
# POOR: Minimal documentation gives CodeBeaver little to work with
def calculate_total(order)
# Implementation
end
# GOOD: Clearly describes what the function does and its expected output
# Calculates the total price of an order including tax and shipping
# Returns a decimal value representing the final price in the order's currency
# The calculation includes item prices, applicable discounts, tax rate, and shipping cost
def calculate_total(order)
# Implementation
end
When CodeBeaver sees the second example, it can generate test cases that specifically verify the inclusion of tax and shipping in the calculation, test with and without discounts, and check currency handling.
2. Specify Input Requirements and Constraints
Explicitly stating what inputs your function accepts helps CodeBeaver generate appropriate test cases, including edge cases:
# POOR: No input specifications
def process_payment(payment)
# Implementation
end
# GOOD: Clearly describes input requirements for CodeBeaver to test
# Processes a payment transaction
# @param payment [Payment] Must be in 'pending' status with a valid amount (> 0)
# @return [Boolean] true if payment was successfully processed, false otherwise
def process_payment(payment)
# Implementation
end
With the second example, CodeBeaver can generate tests for valid payments, payments with zero or negative amounts, and payments in non-pending statuses.
3. Document Expected Return Values and Side Effects
CodeBeaver needs to know what your function returns and any side effects it produces:
# POOR: No return value or side effect documentation
def archive_user(user)
# Implementation
end
# GOOD: Clearly documents return values and side effects
# Archives a user account, preventing login while preserving data
# @param user [User] The user account to archive
# @return [User] The updated user with status changed to 'archived'
# @side_effect Sends an account archival notification email to the user
# @side_effect Logs an audit event in the system
def archive_user(user)
# Implementation
end
This documentation enables CodeBeaver to generate tests that verify the user’s status change, check that notification emails are sent, and confirm audit logs are created.
CodeBeaver-Optimized Code Structure
Beyond documentation, certain code structure patterns help CodeBeaver generate more effective tests.
1. Expose Function Outcomes for Better Testing
Make outcomes of your functions visible and testable:
# HARD FOR CODEBEAVER: Internal state change is difficult to test
def process_order(order)
@processed_orders << order
end
# BETTER FOR CODEBEAVER: Return value makes outcome testable
# Processes an order by adding it to the processed queue
# @param order [Order] The order to process
# @return [Boolean] true if the order was successfully processed, false otherwise
def process_order(order)
result = @processed_orders << order
result.present?
end
The second approach gives CodeBeaver a clear result to verify in its generated tests.
2. State Preconditions and Postconditions
Explicitly stating what must be true before and after a function runs helps CodeBeaver generate more targeted tests:
# UNCLEAR FOR CODEBEAVER: No explicit conditions
def transfer_funds(source, destination, amount)
# Implementation
end
# CLEAR FOR CODEBEAVER: Explicit pre and post conditions
# Transfers funds between accounts
# @param source [Account] Source account (must be active and have sufficient funds)
# @param destination [Account] Destination account (must be active)
# @param amount [Decimal] Amount to transfer (must be positive)
# @return [Transfer] The completed transfer record
# @precondition source.balance >= amount
# @postcondition source.balance decreased by amount
# @postcondition destination.balance increased by amount
def transfer_funds(source, destination, amount)
# Implementation
end
With these conditions explicitly stated, CodeBeaver can generate tests that verify the function behaves correctly when preconditions are met or violated, and that postconditions are satisfied after execution.
Communicating Business Rules to CodeBeaver
Business rules often dictate special cases and edge conditions that should be tested.
1. Document Domain-Specific Rules
Explicitly documenting business rules helps CodeBeaver generate tests for these specific scenarios:
# BASIC: No business rules documented
def apply_discount(order, code)
# Implementation
end
# COMPREHENSIVE: Business rules explicitly documented
# Applies a discount code to an order
# @param order [Order] The order to apply the discount to
# @param code [String] The discount code
# @return [Order] The updated order with discount applied
#
# Business rules:
# - Premium customers receive an additional 5% discount
# - Seasonal codes (starting with 'SEASON') cannot be combined with other discounts
# - Discounts cannot reduce the total below the cost of items (no negative margins)
# - Discount codes can only be used once per customer
def apply_discount(order, code)
# Implementation
end
This documentation enables CodeBeaver to generate tests for each business rule, ensuring all special cases are covered.
2. Explicitly Handle Error Cases
Clearly documenting how errors are handled helps CodeBeaver generate negative test cases:
# MINIMAL: No error handling documentation
def create_user(attributes)
# Implementation
end
# DETAILED: Error cases explicitly documented
# Creates a new user account
# @param attributes [Hash] User attributes including email and password
# @return [User] The created user if successful
# @raise [ValidationError] If email is already taken
# @raise [ValidationError] If password doesn't meet complexity requirements
# @raise [ServiceUnavailableError] If the authentication service is down
def create_user(attributes)
# Implementation
end
This documentation enables CodeBeaver to generate tests that verify the function correctly raises specified exceptions under the right conditions.
Distinguishing Between Code Issues and Test Generation Issues
A common challenge with automatically generated tests is determining whether a failing test indicates a bug in your code or an issue with the test itself.
1. Provide Example Invocations with Expected Results
Including example invocations helps CodeBeaver understand the expected behavior precisely:
# Calculate the total price including tax
# @param items [Array<Item>] The items being purchased
# @param tax_rate [Float] The tax rate as a decimal (e.g., 0.05 for 5%)
# @return [Float] The total price including tax
#
# @example
# items = [Item.new(price: 10.0), Item.new(price: 20.0)]
# calculate_total_with_tax(items, 0.05) # => 31.5
def calculate_total_with_tax(items, tax_rate)
# Implementation
end
When CodeBeaver encounters a failing test for this function, you can compare it against the documented example to determine whether the issue is with your implementation or the test generation.
2. Document Method Invariants
Explicitly stating what should always be true about your function helps CodeBeaver generate tests that verify these invariants:
# Splits a payment across multiple payment methods
# @param amount [Decimal] The total amount to be paid
# @param payment_methods [Array<PaymentMethod>] The payment methods to use
# @return [Array<Payment>] The resulting payment records
#
# @invariant The sum of split payments equals the original amount
# @invariant Each payment method is charged at most once
# @invariant All payments are either successful or none are (atomic operation)
def split_payment(amount, payment_methods)
# Implementation
end
These invariants make it clear to CodeBeaver what must hold true regardless of the specific inputs, helping it generate tests that verify these fundamental properties.
CodeBeaver-Specific Testing Patterns
Some patterns are particularly effective when working with CodeBeaver’s test generation capabilities.
1. Factory Method Pattern for Complex Objects
When your tests require complex objects, using factory methods with clear documentation helps CodeBeaver understand how to create valid test objects:
# DIFFICULT FOR CODEBEAVER: Complex object creation in tests
# CodeBeaver may struggle to create valid Order objects in tests
# BETTER: Factory method with clear documentation
# Creates a valid order for testing purposes
# @param attributes [Hash] Optional attributes to override defaults
# @return [Order] A valid order with line items, customer, and payment
# @example
# create_test_order(customer: customers(:premium))
def create_test_order(attributes = {})
Order.new({
customer: Customer.new(name: "Test Customer"),
line_items: [LineItem.new(product_id: 1, quantity: 1)],
payment_method: "credit_card",
shipping_address: "123 Test St"
}.merge(attributes))
end
With this factory method, CodeBeaver can create valid test objects without needing to understand the complex interdependencies of your domain objects.
2. Use Guard Statements with Explicit Error Messages
When your functions have guard statements, providing explicit error messages helps CodeBeaver understand the expected behavior in error cases:
# UNCLEAR: Error message doesn't explain the constraint
def withdraw(account, amount)
raise "Invalid" unless amount > 0
# Implementation
end
# CLEAR: Error message explains the specific constraint
# Withdraws funds from an account
# @param account [Account] The account to withdraw from
# @param amount [Decimal] The amount to withdraw (must be positive)
# @return [Transaction] The resulting transaction record
# @raise [ArgumentError] If amount is not positive
def withdraw(account, amount)
raise ArgumentError, "Withdrawal amount must be positive" unless amount > 0
# Implementation
end
The explicit error message helps CodeBeaver generate tests that verify the function correctly rejects invalid inputs.
By following these CodeBeaver-specific practices, you’ll significantly improve the quality and accuracy of automatically generated tests. Remember that the key to success with CodeBeaver is providing clear, explicit information about what your code is supposed to do, allowing the AI to generate tests that verify it works as intended.
Optional: Integrating with your CI/CD
While CodeBeaver works great on a per-PR basis, integrating it into your CI/CD pipeline ensures consistent test coverage across your entire development workflow. This integration allows you to:
- Run comprehensive test generation on a schedule
- Ensure test coverage for all new changes
- Track test coverage metrics over time
- Automate the approval and merging of test PRs
Let’s explore how to integrate CodeBeaver with GitHub Actions as a concrete example.
Setting Up GitHub Actions for CodeBeaver
Create a new file at .github/workflows/codebeaver-action.yml
in your repository with the following configuration:
name: CodeBeaver Test Generation
on:
pull_request:
branches: [main, develop]
schedule:
# Run weekly on Monday at 2 AM UTC
- cron: "0 2 * * 1"
workflow_dispatch:
# Allow manual trigger
jobs:
codebeaver-analysis:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.1"
bundler-cache: true
- name: Run CodeBeaver Analysis
uses: codebeaver-io/codebeaver-action@v1
with:
api-key: ${{ secrets.CODEBEAVER_API_KEY }}
analysis-mode: "full"
pr-comment: true
- name: Upload test coverage report
uses: actions/upload-artifact@v3
with:
name: test-coverage-report
path: coverage/
This workflow:
- Runs on pull requests to main or develop branches
- Executes on a weekly schedule (Monday at 2 AM UTC)
- Can be triggered manually when needed
- Performs a full analysis of your codebase using CodeBeaver
- Comments on PRs with coverage information
- Uploads the coverage report as a workflow artifact
Creating a Repository Secret
To use the GitHub Action, you’ll need to add your CodeBeaver API key as a repository secret:
- Go to your repository on GitHub
- Navigate to Settings > Secrets and variables > Actions
- Click “New repository secret”
- Name it
CODEBEAVER_API_KEY
- Enter your CodeBeaver API key (available in your account settings)
- Click “Add secret”
API Integration for Custom Workflows
For teams with specialized CI/CD requirements, CodeBeaver offers a comprehensive API that can be integrated directly into your custom workflows. The API allows you to:
- Trigger test generation programmatically
- Retrieve test coverage metrics
- Generate test reports in various formats
- Integrate with custom notification systems
For detailed API documentation and authentication requirements, refer to the CodeBeaver API Documentation.
Conclusion – Your first Rails Unit Test pipeline
Congratulations! You’ve successfully integrated CodeBeaver with your Rails application and taken a significant step toward maintaining comprehensive test coverage without the manual overhead. Let’s recap what we’ve accomplished:
Key Benefits
- Automated Test Generation: CodeBeaver now monitors your PRs, automatically generating tests that respect Rails conventions and your project’s specific patterns.
- Time Savings: You can focus on building features while CodeBeaver handles the repetitive aspects of test writing.
- Increased Confidence: With comprehensive test coverage, you’ll catch regressions before they reach production.
- Rails-Specific Testing: Unlike generic AI solutions, CodeBeaver understands ActiveRecord relationships, validations, and Rails idioms.
Next Steps
To further enhance your Rails Unit Test strategy:
- Review and Refine: Periodically review CodeBeaver-generated tests to ensure they align with your team’s evolving standards.
- Add Custom Contexts: For domain-specific logic, consider adding additional comments that help CodeBeaver understand your business rules.
- Track Coverage Trends: Use the CI integration to monitor how your test coverage improves over time.
- Expand to System Tests: While CodeBeaver excels at unit tests, consider complementing it with system tests for critical user journeys.
Community Resources
The Rails testing ecosystem offers numerous resources to complement your CodeBeaver integration:
- Rails Guides: The official Rails Testing Guide provides in-depth coverage of Rails testing philosophies.
- RSpec Documentation: For RSpec users, the RSpec Rails documentation offers valuable insights into Rails-specific testing.
- CodeBeaver Community: Join our Discord community to share experiences and best practices with other Rails developers using CodeBeaver.
- If you are interested in Go Unit Tests, we have a tutorial for you as well!
By combining CodeBeaver’s automated test generation with Rails’ robust testing foundations, you’ve established a sustainable approach to maintaining test coverage that scales with your application. Your future self (and your team) will thank you when that next critical bug is caught before it ever reaches production.
Happy testing!