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

A practical Selenium WebDriver Ruby project can start with a Gemfile and one Ruby file; a test suite usually adds a spec/ directory, shared setup, and individual test files. Selenium’s official Ruby example uses RSpec and shows browser startup and cleanup, but Selenium does not require a universal directory layout. Treat the structure below as a convention to grow into, not a framework rule.

Recommended directory structure for a Ruby Selenium project

For an RSpec-based suite, this is a useful starting point:

my_selenium_project/
├── Gemfile
├── Gemfile.lock
├── .rspec                  # optional RSpec command defaults
├── spec/
│   ├── spec_helper.rb      # shared setup and teardown
│   └── example_spec.rb     # browser tests
├── pages/                  # optional reusable page objects
└── support/                # optional shared helpers or configuration

The root holds dependency and runner configuration. Keep test files together under spec/; put shared browser lifecycle code in spec_helper.rb. Add pages/ or support/ only when repeated behavior gives those directories a purpose. Selenium’s official Ruby example requires a spec_helper, but the larger tree above is a practical convention, not a prescribed Selenium layout.

What belongs in each file

  • Gemfile declares gems the project needs, so another developer can install the same dependency set with Bundler.
  • Gemfile.lock records the resolved versions after installation. Commit it for an application or test project when you want repeatable installs.
  • .rspec is optional and can hold RSpec command defaults. A small project can run RSpec without it.
  • spec/spec_helper.rb is the shared place for runner configuration and setup or teardown used by several specs.
  • spec/example_spec.rb contains test examples and their assertions, rather than general-purpose setup duplicated across files.
  • pages/ can hold page-object classes when multiple tests need the same page interactions. It is not needed for a first test.
  • support/ can hold helpers or configuration that do not belong in a particular test or page class.

Choose the smallest structure that fits the job

One-off browser script

If you only need to automate one short task, start with a Gemfile and a Ruby script such as capture_title.rb. A test runner, spec/, and page objects add little value until you have multiple checks to organize or repeat.

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.
#1 Best Overall

Automated test suite

Use a runner once you need named tests, assertions, grouping, or shared setup and cleanup. Selenium’s Ruby documentation demonstrates RSpec and also names Minitest as an option. Pick the runner your team already understands; the documentation does not declare one universally better or faster.

Growing suite

When the same page interactions or setup appear in several tests, move them into shared support or page objects. Keep the tests themselves readable: an example should make clear what behavior it checks, while reusable classes provide the mechanics. Avoid adding empty directories just because they appear in a template.

Install Ruby dependencies and prepare the project

The current Selenium Ruby bindings README states support for MRI Ruby 3.3 and newer. That compatibility floor is from the README generated in September 2026; check the Selenium release you choose for current requirements before adopting a different Ruby implementation or older Selenium release. See the Selenium Ruby bindings documentation.

Selenium’s installation documentation includes a Ruby Gemfile example with selenium-webdriver, RSpec, Rake, RuboCop, and other development tools. It shows selenium-webdriver 4.49.0 and selenium-devtools 0.153.0 as example versions on the page last modified September 16, 2026; those are examples, not evergreen version recommendations. For a minimal RSpec project, create this Gemfile:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
source "https://rubygems.org"

gem "selenium-webdriver"
gem "rspec"

From the project root, install the declared gems and generate the lockfile:

bundle install

Bundler will create or update Gemfile.lock. The official install page also shows installing a gem manually; using a Gemfile is more convenient when dependencies should be managed at project level.

Browser and driver setup

The Selenium Ruby bindings README says Selenium Manager automatically handles browser-driver installation, so a basic project does not need a manually downloaded driver executable checked into its directory. This does not mean the browser itself is unnecessary: the example below starts Chrome, so have Chrome available in the environment where the test runs. When diagnosing startup problems, check the selected Selenium release’s setup guidance as well as local browser availability.

Build a runnable RSpec example with reliable cleanup

Put shared driver setup in spec/spec_helper.rb. Starting a driver before each example gives each test its own browser session; quitting it afterward prevents a completed or failed example from leaving the session running.

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.
# spec/spec_helper.rb
require "selenium-webdriver"

RSpec.configure do |config|
  config.before do
    @driver = Selenium::WebDriver.for :chrome
  end

  config.after do
    @driver&.quit
  end
end

Now add an example file:

# spec/example_spec.rb
require "spec_helper"

RSpec.describe "Example page" do
  it "opens a page and reads its title" do
    @driver.navigate.to "https://example.com"
    expect(@driver.title).not_to be_empty
  end
end

The setup follows the lifecycle shown in Selenium’s official RSpec example: initialize Chrome in a before hook and call quit in an after hook. Run the suite from the project root with:

bundle exec rspec

bundle exec runs RSpec using the project’s bundled dependencies. The assertion here is intentionally modest: it checks that a title was returned, not that a particular site remains unchanged. For a real test, assert the page behavior your application owns, rather than relying on a third-party page’s content.

Alternative: a single Ruby script

For a one-off script, explicit cleanup with ensure is the useful pattern. Selenium’s bindings README quick start uses this approach so cleanup runs even when execution exits through an error:

require "selenium-webdriver"

driver = Selenium::WebDriver.for :chrome

begin
  driver.navigate.to "https://example.com"
  puts driver.title
ensure
  driver.quit
end

Run it with Bundler from the project root:

bundle exec ruby script.rb

Do not put a second driver startup in every test if the shared hook already creates one. Likewise, keep test assertions inside test examples rather than turning the helper into a place where unrelated checks run automatically.

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

Organize shared code without overengineering

RSpec versus Minitest

Selenium’s Ruby guidance recognizes both RSpec and Minitest. RSpec is the runner in the official Selenium Ruby example above, making its hook-based lifecycle a direct starting point. Minitest may suit a project already using its conventions. Choose based on existing team familiarity and the organization your tests need; there is no Selenium-published comparative benchmark establishing a winner.

When page objects help

A page-object directory is useful when several tests repeat the same interactions with the same application page. For instance, a class can own the selectors and actions for a sign-in page while tests describe successful or rejected sign-ins. This separation can reduce repetition, but for one or two short examples it can obscure the behavior rather than clarify it. Add the abstraction in response to repeated test code, not as a prerequisite for Selenium.

Rake and other development tools

Selenium’s example Gemfile includes Rake and RuboCop among its development tools. They can support project-specific tasks and style checks, but neither is required to run the RSpec example above. Start with the runner and Selenium gem; add tools when your team has a task or convention that needs them.

Troubleshoot common project and browser failures

  • Ruby version does not meet the binding requirements: the Selenium Ruby bindings README generated in September 2026 states MRI 3.3 or newer. Confirm the Ruby version used by the command and the compatibility requirements for the Selenium release in your Gemfile.
  • bundle exec rspec cannot find RSpec: check that rspec is in the project Gemfile, run bundle install from the root, and then run the command from that same project.
  • The browser fails to start: confirm Chrome is available in the execution environment and that the Selenium version is compatible with the environment. Selenium Manager handles browser-driver installation according to the bindings README; a manual driver file is not the default project requirement.
  • A browser remains open after a test: confirm the shared after hook calls @driver&.quit. For a standalone script, place work in a begin block and cleanup in ensure.
  • Tests are difficult to maintain: move repeated lifecycle code into the helper, and repeated page interactions into a page object only when reuse justifies it. Keep assertions and the behavior under test visible in the spec.
  • A target site blocks automation or a scraping task stops working: Selenium’s organization guidance notes that some sites prohibit scraping or block Selenium. Review the site’s terms before automating access; do not treat a project structure change as a way around those restrictions.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your actual goal is to save a page image or PDF—not to test interactive browser behavior—you can use ScreenshotNeo, a website screenshot API with an MCP server. It is a screenshot option, not a replacement for Selenium when a test needs to operate a browser. One GET request returns a screenshot or PDF; the example below saves an image. See the ScreenshotNeo API documentation for request options.

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://example.com -o shot.webp

ScreenshotNeo accepts consent banners like a visitor before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with response headers indicating the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.

Scraping is a different use case from testing

Selenium can automate browser behavior, and its organization guide lists web scraping among possible uses. But some sites prohibit scraping or block Selenium. Before building a scraper, review the target site’s terms and account for the possibility that browser automation may not be allowed or may not work. A clean directory layout does not change those constraints.

Keep the project structure proportional to the suite

Start with a Gemfile and either a small script or a runner-backed test directory. Use a shared helper for browser lifecycle, guarantee that each driver is quit, and add support or page-object directories only when shared code makes them useful. Selenium’s own Ruby example is a sound model for the runner-based path; the exact names and the amount of scaffolding should follow the needs of your project.

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

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.