Bug reports and pull requests are welcome on GitHub at https://github.com/snap-diff/snap_diff-capybara. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
- Ruby 3.2+ (the project tests against 3.2–4.0)
- libvips 8.9+ (optional, for the VIPS driver). Install with:
- macOS:
brew install vips - Ubuntu:
sudo apt-get install libvips-dev
- macOS:
- Chrome (for integration tests with
selenium_chrome_headlessorcuprite)
bin/setupThis installs gem dependencies and prepares the development environment.
# All tests
rake test
# Unit tests only (faster, no browser required)
rake test:unit
# Integration tests (require a browser)
rake test:integration
# Run specific test file
ruby -Ilib:test test/unit/image_compare_test.rb
# Run with a specific screenshot driver
SCREENSHOT_DRIVER=vips rake test
# Run with a specific Capybara driver (integration tests)
CAPYBARA_DRIVER=cuprite rake test:integration
# Record new baseline screenshots (integration tests)
RECORD_SCREENSHOTS=1 bin/dtestUse Docker for reproducible CI-matching test runs:
bin/dtest # Run all tests in Docker
bin/dtest test/integration/ # Run specific directorySee docs/docker-testing.md for details.
# Ruby linting (Standard Ruby)
bundle exec standardrb
# Auto-fix
bundle exec standardrb --fixThis project uses Standard Ruby for consistent formatting. Run bundle exec standardrb --fix before committing.
The gem supports Ruby 3.2 through 4.0 (including JRuby). When adding features:
- Avoid syntax or APIs that are only available in newer Ruby versions
- Test with the full matrix (see
.github/workflows/test.yml) - Be mindful of JRuby compatibility (no C extensions, avoid platform-specific code)
- Classes/modules:
CamelCase(Ruby convention) - Methods:
snake_case - Test files:
snake_case_test.rb(matching the class they test) - Screenshot names: descriptive, kebab-case or snake_case
- Value objects — immutable data carriers (e.g.,
Difference,Comparison,Region) - Strategy pattern — interchangeable algorithms (e.g.,
VipsDriver/ChunkyPNGDriver) - Layered comparison — fast-then-slow strategy in
ImageCompare(byte → pixel → region) - Thread safety — thread-local state for per-test data, mutex for shared state
- Test doubles — use
TestDoubles::TestDriverandTestDoubles::TestPath(seetest/support/test_doubles.rb)
- Service objects — this codebase prefers explicit method calls over service object wrappers
- Global state mutation at runtime — configuration should be set once before tests
- Monkey-patching — prefer composition over patching Capybara internals
- Run the full test suite —
rake testshould pass - Run the linter —
bundle exec standardrbshould pass - Add tests for new functionality or bug fixes
- Update docs if changing behavior or adding features
- Update CHANGELOG.md under the
[Unreleased]section
Include:
- What changed (one-line summary)
- Why it changed (motivation, related issue)
- How it was tested
- Screenshots if the change affects visual output
- A maintainer will review your PR
- Address review feedback with additional commits (no force-pushing)
- Once approved, a maintainer will merge
- Unit tests go in
test/unit/and test a single class in isolation. Use test doubles fromtest/support/test_doubles.rbrather than testing with real image files or browsers. - Integration tests go in
test/integration/and exercise the full capture → compare → report pipeline with a real browser. These are slower and require Chrome. - Driver contract tests (
test/support/driver_contract_tests.rb) verify that all image processing drivers meet the same interface. Add a contract test when adding a new driver method. - Test environment isolation: each unit test snapshots and restores
Capybara::ScreenshotandCapybara::Screenshot::Diffglobal state. Don't mutate globals outside of setup/teardown.
- Create
lib/capybara/screenshot/diff/drivers/new_driver.rbinheriting fromBaseDriver - Implement required methods:
load_images,from_file,save_image_to,same_pixels?,find_difference_region,crop,add_black_box,draw_rectangles,resize_image_to - Register in
Utils.detect_available_driversandUtils.find_driver_class_for - Add driver contract tests in
test/unit/drivers/new_driver_test.rb - Add integration tests exercising the new driver
- Create
lib/capybara_screenshot_diff/reporters/new_reporter.rb - Implement
record(assertions)andfinalizemethods - Register with
CapybaraScreenshotDiff.reporters << MyReporter.new - Add tests in
test/unit/reporters/
To release a new version:
- Update the version number in lib/capybara/screenshot/diff/version.rb
- Update CHANGELOG.md with the new version and date
- Create a GitHub Release:
- Go to Actions → Release
- Click Run workflow, enter the version number
- The workflow will: test → tag → publish to RubyGems → create GitHub Release
Or manually:
bundle exec rake releaseThis creates a git tag, pushes commits and tags, and pushes the .gem file to rubygems.org.