Using Puma and Capybara for integration testing
When running integration tests in Rails using Capybara and Capybara Webkit engine, its always easy to forget that the application server used to run your tests is not the same as the one you would normally use in production or even development environments.
Rails has a very simple set of defaults when it comes to the tech stack. So, lets
say you just started a new app and need to fire up the development server. With
just rails server
you'll get Webrick running on localhost:3000
. Awesome, but
the problem is that webrick is not a good choice for production use, so most people
these days either use Puma or Unicorn, which are very similar in design and
build for concurrency.
I personally prefer Puma and use it in development/production environments in tandem with Foreman. Using the same app server stack in every step of development pipeline makes it easy to spot bugs, so why not use it for integration tests?
Here's how its done. First, make sure that you have somewhat recent version of Puma
bundled into application, and edit your rails_helper.rb
file:
# Bunch of default rails requires
require "spec_helper"
require File.expand_path("../../config/environment", __FILE__)
require "rspec/rails"
# Load capybara api
require "capybara/rspec"
require "capybara/rails"
require "capybara/webkit"
# Pretty much defaults
Capybara.default_driver = :webkit
Capybara.javascript_driver = :webkit
# Here's the meat part, we'll register our own server handler.
require "puma"
Capybara.register_server("puma") do |app, port|
server = Puma::Server.new(app)
server.add_tcp_listener(Capybara.server_host, port)
server.run
end
If you're running spring or any other preloader, there's a big chance that you'll have to restart it. Capybara server handlers are pluggable and you can always switch runner to another server of your choice.