Helpers for testing Tony.
source: 'https://www.jubigems.org/' do
gem 'core-test'
gem 'tony-test'
end
tony-test
is designed for use with RSpec
on top of either rack-test
for basic http testing, or capybara
for testing inside a Chrome browser, with Javascript support and the ability to capture screenshots.
In your spec_helper.rb
:
require `tony-test`
RSpec.shared_context(:rack_test) {
include_context(:tony_rack_test)
let(:app) {
# Create your tony app here. Tony::App.new or whatever.
}
let(:cookie_secret) {
# Return the same cookie secret string the app will be using.
}
}
RSpec.configure do |config|
config.include_context(:rack_test, type: :rack_test)
end
Now in any individual _spec.rb
test file:
# `type: :rack_test` will pull in the helpers for rack-test.
RSpec.describe(MyTonyApp, type: :rack_test) {
it('does something') {
# You can set cookies
set_cookie(:key, 'value')
# Standard stuff you do in rack-test
get '/'
# All standard Capybara matchers are available
expect(last_response.body).to(have_selector('p.class'))
expect(last_response.ok?).to(be(true))
# You can wait until fontawesome has loaded.
expect(last_response.body).to(have_fontawesome)
# You can wait until the timezone has been loaded.
expect(last_response.body.to(have_timezone)
}
# You can simply assert a slim template is rendered with specific params.
it('just tests a slim render is called') {
# All the keys must be passed to a Slim template at `my_template`.
# Note how you can use RSpec matchers here, or simple items for == testing.
expect_slim(:my_template, param: contains('some substr'),
another: an_instance_of(MyClass),
values: match_array(['tony', 'bennett']),
other: 'exact match')
get '/'
}
# You can assert a slim template is rendered with any params
it('just tests any slim render is called with template') {
expect_any_slim(:my_template)
get '/'
}
# You can also pass the specific keys `layout:` and `views:` to insist the
# slim template includes a specific layout and comes from a specific views
# directory.
it('tests a slim render has specific view and layout') {
expect_slim(:template_name, views: 'view_dir', layout: 'our_layout_file')
get '/'
}
}
In your spec_helper.rb
:
require `tony-test`
# Of course you need to set Capybara.app here and call Capybara.register_driver
# and anything else to set up Capybara as per its documentation.
RSpec.shared_context(:capybara) do
include_context(:tony_capybara)
let(:cookie_secret) {
# Return the same cookie secret string the app will be using.
}
end
RSpec.configure do |config|
config.include_context(:capybara, type: :feature)
end
Now in any individual _spec.rb
test file:
# `type: :feature` will pull in all the helpers for capybara.
RSpec.describe(MyTonyApp, type: :feature) {
it('does something') {
# You can set cookies
set_cookie(:key, 'value')
# Standard stuff you do in capybara
visit('/')
# All standard Capybara matchers are available
expect(page).to(have_selector('p.class'))
# You can wait until fontawesome has loaded.
expect(page).to(have_fontawesome)
# You can wait until the timezone has been loaded.
expect(last_response.body.to(have_timezone)
# There's several custom matcher for capybara elements.
# Each will wait the `Capybara.default_max_wait_time` or take a `wait:`
# parameter for custom wait lengths.
expect(page.find('#my-input-element')).to(have_focus)
expect(page.find('#my-button')).to(be_disabled)
expect(page.find('#my-element')).to(be_visible)
expect(page.find('#my-element')).to(be_gone)
}
}
tony-test
offers a system for storing "golden" screenshots of your app which it can test for changes during a test run. If any screenshots have changed, it will launch its own local Tony
webserver and open a browser where you can review those changes and choose whether to accept the new images as the new goldens. If you accept, it will copy the new image into your git repo, overwriting the original.
Example usage:
RSpec.describe(Poll, type: :feature) {
# Second param is the folder of your goldens, defaults to `spec/goldens`.
let(:goldens) { Tony::Test::Goldens::Page.new(page) }
visit('/')
# Checks for a golden image in `spec/goldens/index_page.png`.
# If none exists (your first run), it will create one for you.
goldens.verify('index_page')
}
Screenshots may differ slightly from environment to environment. You can tell tony-test
to allow a certain amount of variability by setting the ENV['GOLDENS_PIXEL_TOLERANCE']
. The value represents a percentage, so 5
means an allowance of 5% difference between the golden and the current screenshot.
You can also increase the tolerance on a specific golden by passing pixel_tolerance:
to a call to goldens.verify()
In some scenarios you may want tony-test
to hard fail if a golden does not match. You can enable this by setting ENV['FAIL_ON_GOLDEN']
to any value. In Github Actions
this will happen by default with no need to set any environment value.
In some scenarios you may want your capybara tests to run but just auto-pass all your calles to goldens.verify()
. In this case you can set ENV['SKIP_GOLDENS']
to any value.
When in Github Actions
, tony-test
will save your screenshots in a sub failures
folder inside your original goldens folder. It will also generate and save a "diff" image visualizing the differences in a diffs
folder. You can then add these files to your artifacts so you can view the failures.
Here is how you could use all your options to set things up inside Github Actions
:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Ruby
uses: ruby/setup-ruby@v1.87.0
with:
ruby-version: 3.0.2
bundler-cache: true
- name: Run tests
run: |
bundle exec rake spec
env:
APP_ENV: test
GOLDENS_PIXEL_TOLERANCE: 0.05
RACK_ENV: test
- name: Upload screenshots
uses: actions/upload-artifact@v2
if: failure()
with:
name: golden-failures
path: |
spec/**/failures/*.png
spec/**/diffs/*.png
if-no-files-found: ignore
The gem is available as open source under the terms of the MIT License.