In part one, we created a rails 6 engine for our users. Part two will focus on testing. The source code is on github.
Testing Our Engine
One of the benefits of a modular monolith is the ease of testing. However, each engine must be configured to test in isolation. It would be ideal to extend common test configuration to reduce setup time and keep things consistent across the application. We extracted our config into a gem, common_testing
.
Since common_testing
is opinionated and can vary across products we use it as a local gem. The gem lives in our host app’s/gems
folder. Alternatively, you can read Adding rspec to a rails engine.
Let’s clone common_testing into our gems folder.
./host_app $ mkdir -p ./gems
./host_app $ cd ./gems
./host_app/gems $ git clone https://github.com/amrani/common_testing.git
Bundle and remove git.
./host_app/gems $ cd ./common_testing
./host_app/gems/common_testing $ rm -rf .git
./host_app/gems/common_testing $ bundle install
You will find our shared rails and spec helpers in the lib folder.
Let’s add this gem to our ConnectBy engine.
# engines/connect_by/Gemfile
group :development, :test do
gem "common_testing", path: "../../gems/common_testing"
end
# engines/connect_by/connect_by.gemspec
spec.add_development_dependency "common_testing"
./host_app/engines/connect_by $ bundle install
Create the engine specific rails and spec helper. Then we can load the shared helper’s from the common_testing
gem.
# engines/connect_by/spec/rails_helper.rb
ENGINE_ROOT = Pathname.new(File.expand_path("..", __dir__))
ENV["RAILS_ENV"] = "test"
require "common_testing/shared_rails_helper"
# engines/connect_by/spec/spec_helper.rb
require "bundler/setup"
require "common_testing/shared_spec_helper"
Add a .rspec
config file and require our local spec-helper.
./host_app/engines/connect_by $ echo "--require spec_helper" > .rspec
Check if everything is working by running rspec spec
in your engines root
./host_app/engines/connect_by $ rspec spec
No examples found.
Finished in 0.00026 seconds (files took 0.08725 seconds to load)
0 examples, 0 failures
Now we should add a test.
# engines/connect_by/spec/models/connect_by/user_spec.rb
require "rails_helper"
RSpec.describe ConnectBy::User, type: :model do
it { expect(true).to be_truthy }
end
APP_RAKEFILE
is configured by ./engines/connect_by/Rakefile
to use dummy app’s. That way we can run our migrations in the engine’s root.
When we generated connect_by
, we used the option --dummy_path=spec/dummy
. Your dummy app should be in ./engines/connect_by/spec/dummy
.
NOTE: If you didn’t, you will need to setup a dummy app and update your engine’s Rakefile.
# engines/connect_by/Rakefile
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
load "rails/tasks/engine.rake"
Setup the database
The engine’s dummy app, by default, prepends each database with dummy_app. To avoid name collisions with another engine dummy app, let’s alter the database.yml
. I’ll use a format with app_name
, engine_name
, "dummy_app"
, and env
,
# ./engines/connect_by/spec/dummy/config/database.yml
test:
<<: *default
database: host_app_connect_by_dummy_test
Now setup our test db and run migrations.
./host_app/engines/connect_by $ RAILS_ENV=test rails db:setup
./host_app/engines/connect_by $ rspec spec
.
Finished in 0.02621 seconds (files took 1.07 seconds to load)
1 example, 0 failures
Factory Bot
I’ll add to my engine’s generators to use factory-bot
.
module ConnectBy
class Engine < ::Rails::Engine
...
config.generators do |g|
g.test_framework :rspec
g.fixture_replacement :factory_bot
g.factory_bot dir: "spec/factories"
end
Takeaway
We added rspec
and factory-bot
to a rails 6 engine. Our shared configuration and dependencies were added to a local gem and referenced by our engine.
The source code for this part is on github.
Next Steps
In Part 3, we will cover how we pass host app configuration options to our engine.
- Part 1 - Create Your First Rails Engine
- Part 2 - Test Your First Rails Engine
- Part 3 - Configure Your First Rails Engine
Useful Resources
I have compiled a list of useful resources for rails engines and the modular monolith architecture.
Scale With Rails Engines
Need help scaling your rails application with a modular monolith? Talk to us
Found this useful? Have a suggestion? Get in touch at blog@hocnest.com
.