spree_dev_tools gem that helps you write Spree-specific tests.
This guide assumes you’ve completed all previous tutorials through API. You should have a complete
Spree::Brand model with admin features and API endpoints.Setup
If your app came from create-spree-app or spree-starter, the test environment is already set up — RSpec, Factory Bot, Capybara, DatabaseCleaner, and thespree_dev_tools helpers (stub_authorization!, the 'API v3 Store' shared context, Spree factories) ship preconfigured in spec/support/. Skip to creating the fixtures file below.
Setting up an app that doesn't have RSpec yet
Setting up an app that doesn't have RSpec yet
For an existing Rails app without test setup, install RSpec and the Spree test helpers:The
spree_dev_tools generator adds the Spree-specific helpers to spec/support/: authorization helpers (stub_authorization!), Factory Bot configuration, Capybara setup for feature tests, and more.Create the Fixtures Directory and File
When writing tests that involve file attachments (like images, PDFs, etc.), you need fixture files that your factories can use. Here’s how to set them up.What the generators already created
If you usedspree generate api_resource in the API step, you already have controller specs (spec/controllers/spree/api/v3/store/brands_controller_spec.rb and …/admin/brands_controller_spec.rb) and a factory (spec/factories/spree/brand_factory.rb). The sections below build the same things by hand — compare as you go, and keep whichever you prefer.
For the model spec, create spec/models/spree/brand_spec.rb — we’ll fill it in below.
Writing Factories
Factories provide a convenient way to create test data. Create a factory for your Brand model:spec/factories/spree/brand_factory.rb
Factory Usage Examples
Writing Model Tests
Model tests verify your business logic, validations, associations, and scopes.spec/models/spree/brand_spec.rb
Testing Decorators
When you extend core Spree models with decorators (see Extending Core Models), test the added functionality:spec/models/spree/product_decorator_spec.rb
Writing Controller Tests
Controller tests verify that your endpoints respond correctly and perform the expected actions.Store API Controller Tests
Test the API endpoints we created in the API tutorial. Store API tests use the'API v3 Store' shared context which sets up a store, publishable API key, and JWT tokens — it ships in the spree_api gem, so require spree/api/testing_support/v3/base at the top of the spec.
spec/controllers/spree/api/v3/store/brands_controller_spec.rb
Testing the Product Brand Association
Test that the custom Product serializer includes brand data:spec/controllers/spree/api/v3/store/products_brand_spec.rb
Admin Controller Tests
spec/controllers/spree/admin/brands_controller_spec.rb
Writing Feature Tests
Feature tests (also called system tests) simulate real user interactions using Capybara.Admin Feature Tests
spec/features/spree/admin/brands_spec.rb
Test Helpers
Authorization Helper
Usestub_authorization! to bypass authorization checks in admin tests:
wait_for_turbo Helper
When testing with Turbo/Hotwire, usewait_for_turbo to ensure the page has fully loaded:
Running Tests
Prepare the test database
Tests run against a dedicatedspree_test database, so your development data is never touched. Create it and load the schema once:
rails_helper.rb re-syncs the test schema automatically when you add migrations. It’s the command to reach for when the test database gets into a broken or out-of-sync state.
Run the suite
spree rspec runs bundle exec rspec inside the web container with RAILS_ENV=test. Everything after rspec is passed through, so file paths, line numbers, and flags work as usual:
Troubleshooting: DatabaseCleaner refuses a remote database URL, or tests hit the development database
Troubleshooting: DatabaseCleaner refuses a remote database URL, or tests hit the development database
Projects scaffolded before July 2026 set Then restart the stack (
DATABASE_URL in docker-compose.dev.yml. A URL overrides config/database.yml for every Rails environment, so in-container tests pointed at the development database and tripped DatabaseCleaner’s remote-URL safeguard. Two small changes bring an older project up to date:- In
docker-compose.dev.yml, replace theDATABASE_URLentry underenvironment:with host/username parts, so each Rails environment resolves its own database fromdatabase.yml:
- In
spec/rails_helper.rb, force the test environment — the dev container bakes inRAILS_ENV=development:
Ctrl+C and spree dev) so the container picks up the new environment.Best Practices
Use build over create
Use
build instead of create when you don’t need a persisted record. It’s faster because it skips database operations.Use let over instance variables
Prefer
let and let! over instance variables. They’re lazily evaluated and scoped to each example.One assertion per test
Keep tests focused on a single behavior. Use
aggregate_failures if you need multiple assertions.Test behavior, not implementation
Focus on what the code does, not how it does it. This makes tests more resilient to refactoring.
Example: aggregate_failures
Complete Test Suite Structure
After completing this tutorial, your test structure should look like:Related Documentation
- Model Tutorial - Creating the Brand model
- Admin Tutorial - Building the admin interface
- Extending Core Models - Connecting Brands to Products
- API Tutorial - Creating Brand API endpoints
- Spree CLI -
spree rspecand the other dev workflow commands - RSpec Documentation - Official RSpec docs
- Factory Bot Documentation - Factory Bot guide

