What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Do not start by increasing Capybara.default_max_wait_time. First identify which layer timed out: Capybara’s synchronization wait, a Selenium/browser command, the Rails test server, application boot or asset compilation, or the RSpec process itself. A larger Capybara wait helps only the first case. Isolate the failing example, replace arbitrary sleeps with synchronization-aware matchers, verify the driver and server, then investigate time control, network stubs and CI differences.

1. Identify the timeout layer before changing a setting

Read the complete exception and run one failing example by itself. The error usually points to the layer that needs repair.

Symptom or exception family Likely layer First check
Expectation or selector failure after waiting Capybara synchronization Use a waiting matcher and verify the selector or expected state.
Selenium transport error, browser crash or lost session Browser or driver Check browser/driver versions, JavaScript requirement and session startup.
Connection refused, server cannot bind, or boot never completes Rails test server or application boot Inspect server output, port configuration and asset compilation.
The test runner stops making progress without a useful exception Clock, network, deadlock or RSpec process Check frozen time, WebMock, open connections and the first command that stops.

When available, save Capybara’s failure screenshot and the server log. Those two artifacts often distinguish a page that never loaded from a page that loaded but never reached the expected state. There is no authoritative universal timeout value: hardware, application work and CI environment determine the appropriate limits.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Replace sleeps with Capybara synchronization

Capybara’s documentation describes its synchronization as powerful enough that you should not manually wait for asynchronous processes to complete. Predicates and RSpec matchers retry failed conditions up to default_max_wait_time.

Use a waiting matcher

Prefer this:

expect(page).to have_content("Order complete")

over this:

sleep 2
expect(page.body).to include("Order complete")

have_content keeps checking until the content appears or the configured wait expires. The non-waiting body assertion runs only once after an arbitrary delay, so it can be flaky when the request takes longer or waste time when it finishes sooner.

Be careful with negative assertions

Capybara documents an important distinction: has_no_xpath? waits after a failed check, while a negated successful predicate can return immediately. Express disappearance with a negative matcher or predicate that Capybara can synchronize, rather than negating a check that has already succeeded:

expect(page).to have_no_css(".spinner")
# or
expect(page).not_to have_css(".spinner")

Choose the form that matches the state transition you need and confirm it against your Capybara version’s matcher behavior.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Tune default_max_wait_time narrowly

Set a sensible project default

Capybara shows this configuration example:

Capybara.default_max_wait_time = 5

Five seconds is an example from the current README, not a universal recommendation. Keep the global value near the time your application normally needs. A very high global value makes every genuine selector failure take longer to report and can make a large suite appear hung.

Give one slow operation more time

Use a per-call wait for a known slow transition instead of penalizing every example:

expect(page).to have_content("Report ready", wait: 15)
expect(page).to have_css("#large-chart", wait: 20)

If a particular session needs a different baseline, configure that session. In Capybara’s threadsafe mode, the documented pattern is:

my_session.config.default_max_wait_time = 10

This changes that session without changing another session’s value. If a request consistently needs an unusually large wait, investigate the application or test design rather than hiding the delay globally.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

4. Match the driver to the example

RSpec system specs use Capybara and, in the cited RSpec documentation, default to Selenium with Chrome. A real browser is appropriate for user interactions and JavaScript, but unnecessary for an HTTP-only assertion.

Keep non-JavaScript examples on :rack_test

Capybara’s RSpec guide allows non-JavaScript examples to use the faster :rack_test driver. Mark only browser-dependent examples with js: true, or select a JavaScript-capable driver explicitly:

RSpec.describe "Checkout", type: :system do
  it "shows the confirmation", js: true do
    visit "/checkout"
    expect(page).to have_content("Confirmation")
  end
end

If the example does not inspect rendered UI or execute JavaScript, move it to a request spec. Request specs exercise the HTTP layer without a browser and are faster than feature or system specs.

Check browser startup separately

If the failure occurs while creating a Selenium session, changing Capybara’s selector wait cannot repair it. Record whether Chrome starts, whether the driver can connect, and whether the first navigation succeeds. Compare local and CI browser, driver and Selenium versions before changing application waits.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

5. Verify the Rails test server and boot path

Capybara supports explicit server configuration, including Puma:

Capybara.server = :puma

RSpec Rails’ system integration requires both Capybara and a webserver. If either dependency is missing, the integration aborts; if the server cannot bind its port or stalls compiling assets, a selector wait is irrelevant.

Diagnose startup failures

  • Run the isolated example and watch the server log from process start.
  • Check for a port already in use, a bind failure or a server process that exits immediately.
  • Measure application boot and asset compilation separately from browser navigation.
  • Confirm that the test database and required environment variables are available in CI.

Do not “fix” a server that never starts by setting a larger default_max_wait_time; repair the boot or server configuration and then rerun the isolated example.

6. Check time control and network stubs

Frozen time can prevent a timeout

Capybara warns that freezing time can be problematic on Ruby/platform combinations without a monotonic process clock. Ajax timing can stop advancing, so a condition that should fail after a wait instead hangs. Use a time-travel approach that preserves elapsed-time measurement where appropriate, and temporarily disable the freeze around a browser interaction to confirm the diagnosis.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Investigate WebMock connection exhaustion

Capybara documents a “Too many open files” failure mode in which repeated requests during a timeout create many connections. When WebMock is enabled, investigate its documented workaround:

WebMock.allow_net_connect!(net_http_connect_on_start: true)

Apply this only according to your test policy and WebMock setup. Also inspect whether a stub is blocking the application’s own test-server request or an asset request. A blocked request can look like a Capybara timeout while the real issue is an incomplete network stub.

7. Reduce unnecessary browser coverage

Use browser specs for behavior a user experiences: rendered UI, JavaScript, navigation and browser-specific interaction. Move controller-independent HTTP behavior to request specs. This reduces browser startup, server traffic and synchronization exposure without reducing coverage of the underlying endpoint.

  • Request spec: status codes, response bodies, authorization and JSON contracts.
  • System or feature spec: visible content, form interaction, JavaScript and end-to-end user flows.
  • Unit or service spec: domain behavior that does not require HTTP or a browser.

Fewer browser examples also make a failing CI run easier to diagnose because each remaining failure represents a genuine browser-level requirement.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

8. Make local-versus-CI differences measurable

There is no single official CI timeout that fits every project. Compare the environments instead of guessing:

  • Ruby, Rails, Capybara, Selenium, Chrome and Chromedriver versions.
  • Database engine/version and test-data setup.
  • Asset pipeline mode and compilation time.
  • Server startup duration and browser-session creation duration.
  • The first command that stops producing output.

Run the failing example alone in CI, preserve server logs and screenshots, and record timestamps for boot, session creation and first navigation. If the isolated example passes but the suite hangs, look for leaked sessions, global state, open connections or an example that freezes the clock. If it fails alone, keep the investigation focused on its driver, server and application path.

9. A repeatable repair workflow

  1. Isolate: run the exact example, for example bundle exec rspec spec/system/orders_spec.rb:42.
  2. Classify: label the failure as Capybara wait, Selenium/browser, server/boot or process-level.
  3. Capture evidence: retain the exception, server log and failure screenshot.
  4. Remove sleeps: replace them with Capybara matchers, predicates or a selector-based wait.
  5. Check the driver: use :rack_test for non-JavaScript coverage and a JavaScript driver only where required.
  6. Check the server: verify dependencies, port binding, Puma configuration and asset compilation.
  7. Check clocks and stubs: remove problematic time freezes and inspect WebMock connection behavior.
  8. Tune locally: use a per-call or session wait for a proven slow operation; change the global value only when the whole application needs it.
  9. Re-run the suite: compare runtime and failure diagnostics before and after the change.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

10. Capturing a failure page without maintaining browser setup

When you need a clean reference image of a page involved in a test failure, ScreenshotNeo (https://screenshotneo.com) provides a website screenshot API and MCP server. It accepts a URL and returns PNG, JPEG, WebP or PDF. Cookie/consent banners, newsletter popups and chat widgets are removed before capture; bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result.

Or skip the browser setup

One GET request is enough (see the ScreenshotNeo API documentation):

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

For test and debugging workflows, the useful distinctions are plain: consent banners, popups and chat widgets are removed before the shot; bot checks, blank pages and failed loads are never billed; an MCP server lets AI agents take screenshots; and 1,000 screenshots a month are free with no card. Paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

11. Troubleshooting by symptom

“The matcher times out, but the page looks correct.”

Confirm that the matcher targets visible text or the correct selector, then inspect asynchronous state and network stubs. Capture the page at failure and use a narrowly increased wait: only after confirming the operation is legitimately slow.

“The suite hangs only in CI.”

Compare dependency and browser versions, server and asset startup times, database readiness and environment variables. Preserve the first failing command’s output; do not assume CI needs a larger Capybara wait.

“Selenium reports a browser or transport error.”

Run the example with the same browser/driver versions as CI, verify session creation independently and ensure the spec actually requires JavaScript. A non-JavaScript example may be exposing an unnecessary browser dependency.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

“The process never reaches a failure.”

Check frozen time, open network connections, WebMock behavior and leaked browser sessions. A non-monotonic clock or connection exhaustion can prevent the normal timeout path from completing.

“Increasing the global wait made the suite much slower.”

Revert the global increase and set a per-call or session wait for the identified slow operation. Keep ordinary failures fast and visible.

Frequently Asked Questions

Does default_max_wait_time control Selenium’s command timeout?

No. It controls Capybara’s synchronization-aware predicate and matcher retries. Selenium transport, browser, server and process-level timeouts require separate diagnosis.

When should I use a system spec instead of a request spec?

Use a system spec when rendered UI, JavaScript or real user interaction is part of the behavior. Use a request spec for HTTP-level behavior that does not require a browser.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Is five seconds the correct Capybara wait for every project?

No. Five seconds is the example value shown in Capybara’s current README, not a universal recommendation.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.