Capybara: Acceptance Test Framework for Ruby Web Applications
Acceptance test framework for web applications
At a glance
- What is it?
- Capybara is a Ruby gem that simulates user interaction with web applications in automated tests. It provides a driver-agnostic DSL that works with Rack::Test for fast headless tests and Selenium for JavaScript-heavy flows, without changing the test code between drivers.
- Who is it for?
- Capybara is the standard choice for acceptance testing Rails and Rack applications in Ruby. It removes the manual wait-for-AJAX problem that makes browser-driven tests brittle, and it lets teams switch from headless to a real browser without rewriting tests.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 78 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Problem Capybara Solves
Acceptance tests for web applications often fail not because the feature is broken but because the test tried to interact with an element before JavaScript finished loading it. Writing explicit sleeps or polling loops in test code is fragile and slow. Capybara eliminates this problem with built-in synchronization: it retries finding elements and waiting for conditions automatically, without the test author specifying how long to wait.
Capybara also abstracts over the underlying driver. A test written with `visit`, `fill_in`, and `click_button` runs against Rack::Test (in-process, no browser, no JavaScript) or against Selenium (a real browser, full JavaScript) by changing a single configuration line. This matters for test suites that want fast headless coverage for most cases and a full browser only for JavaScript-heavy flows.
The README states that Capybara is agnostic about the driver running your tests, which is the architectural decision that makes the tool long-lasting. Individual acceptance tests do not need to know whether they are running against a headless process or a visible browser. That separation has practical value: a CI environment can run the full suite against Rack::Test for speed, while a developer investigating a visual bug switches a single test to Selenium with one annotation.
Installation and Setup
Capybara requires Ruby 3.0.0 or later. To add it to a project, put this line in the `Gemfile` and run `bundle install`:
gem 'capybara'For a Rails application, add this to the test helper file:
require 'capybara/rails'For a Rack application that is not Rails, set `Capybara.app` to the Rack app:
Capybara.app = MyRackAppIf the application uses Rails 5.0 and above but not Rails system tests from 5.1, the README recommends switching the server to Puma to match Rails defaults:
Capybara.server = :puma
Capybara.server = :puma, { Silent: true }For JavaScript tests, or for applications at a remote URL, a different driver is required. The README documents Selenium as the default JavaScript driver.
Writing Tests with the Capybara DSL
Capybara's DSL is designed to read like a description of user behavior. The most common methods are `visit` (navigate to a URL), `fill_in` (type into a form field), `click_button` (submit), and `within` (scope interactions to a CSS selector).
An RSpec example from the README shows a sign-in test:
describe "the signin process", type: :feature do
before :each do
User.create(email: '[email protected]', password: 'password')
end
it "signs me in" do
visit '/sessions/new'
within("#session") do
fill_in 'Email', with: '[email protected]'
fill_in 'Password', with: 'password'
end
click_button 'Sign in'
expect(page).to have_content 'Success'
end
endThe same DSL works in Cucumber step definitions:
When /I sign in/ do
within("#session") do
fill_in 'Email', with: '[email protected]'
fill_in 'Password', with: 'password'
end
click_button 'Sign in'
endSwitching to a JavaScript driver for a specific RSpec example uses `js: true`:
describe 'some stuff which requires js', js: true do
it 'will use the default js driver'
it 'will switch to one specific driver', driver: :selenium
endIn Cucumber, tagging a scenario with `@javascript` triggers the JavaScript driver.
Driver Architecture: Rack::Test vs. Selenium
Capybara ships with two built-in drivers. Rack::Test is an in-process driver that interacts with the Rack application directly, without starting a browser. It is fast and deterministic but does not execute JavaScript. Selenium drives a real browser (Chrome or Firefox by default) and handles JavaScript, but it is slower and requires the browser and a WebDriver binary to be installed.
The Docker Compose file in the repository shows how to run Selenium in a container for CI:
version: "3"
services:
selenium_chrome:
network_mode: "host"
image: "selenium/${SELENIUM_IMAGE:-standalone-chrome}"
volumes:
- "/dev/shm:/dev/shm"WebKit support is available through an external gem, not bundled with Capybara.
The README also mentions threadsafe mode, which allows different threads to use different Capybara sessions simultaneously. This is relevant for test suites that run examples in parallel.
Limitations and Cases Where It Does Not Fit
Capybara is built around Rack and Rails conventions. Testing a non-Rack web application, such as a service that speaks a custom protocol or a desktop Electron app, requires a completely different approach.
The synchronization features that eliminate manual waits assume that elements eventually appear. For applications where a component genuinely should not appear, writing a negative assertion requires using `have_no_content` or similar negative matchers rather than asserting the absence of content that might just be slow to load.
XPath usage has a documented trap: using `//` in an XPath expression searches the entire document from the root, not just within the current scope. The README calls this out explicitly as a gotcha. CSS selectors are safer for scoped queries.
The project does not accept external contributions; the README points users to GitHub Discussions for questions. The project relies on Patreon and financial supporters for ongoing development.
Transactions and database setup require attention when using Selenium. Because Selenium tests run in a separate process from the Rails app, database transactions used to roll back test data are not visible to the server process. The README addresses this in the Transactions and database setup section but does not include a ready-made solution; teams using database cleaner strategies must configure them explicitly.
Test Framework Integrations and Maintenance
Capybara integrates with RSpec, Cucumber, Test::Unit, Minitest, and Minitest::Spec. For RSpec, specs in `spec/features` or `spec/system` are automatically treated as feature tests when using Capybara with Rails. For Cucumber, the `cucumber-rails` gem includes Capybara support; non-Rails projects load `capybara/cucumber` manually.
The gem is licensed under MIT. The last push was on 2026-07-13, which is under six months before the current date.
Capybara's DSL includes session management for tests that need to simulate multiple simultaneous users. The README documents both named sessions and using sessions manually, which is relevant for testing workflows where one user's action should affect another user's view. The threadsafe mode allows each thread to use a separate session, enabling parallel test execution frameworks to run Capybara tests without interference between test cases. A Docker Compose setup for Selenium Chrome and Firefox is included in the repository for teams that want to run browser tests in a containerized CI environment.
Editorial conclusion
Capybara is the standard choice for acceptance testing Rails and Rack applications in Ruby. It removes the manual wait-for-AJAX problem that makes browser-driven tests brittle, and it lets teams switch from headless to a real browser without rewriting tests. The main limitation is JavaScript coverage: Rack::Test does not execute JavaScript, so any test that depends on client-side behavior must use Selenium or a WebKit driver. Teams working outside the Rails or Rack ecosystem should evaluate whether Capybara's integration assumptions apply to their stack. The last push was on 2026-07-13.
Frequently asked questions
Does Capybara work with Rails?
Yes. The README states no setup is necessary for Rails and Rack applications; Capybara works out of the box. For Rails apps, require 'capybara/rails' in the test helper. Specs placed in spec/features or spec/system are automatically recognized as Capybara feature tests.
What drivers does Capybara support?
Capybara ships with Rack::Test and Selenium built in. WebKit support is available through an external gem. Rack::Test runs in-process without a browser; Selenium drives a real browser and handles JavaScript. The driver is switched with a single configuration change without rewriting tests.
Does Capybara handle asynchronous JavaScript?
Yes. The README describes this as a key benefit: Capybara's synchronization features mean you never have to manually wait for asynchronous processes to complete. It retries element lookups automatically when using a JavaScript-capable driver such as Selenium.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/teamcapybara-capybara)