Code Monkey home page Code Monkey logo

rspec-rails-examples's Introduction

RSpec Rails Examples Build Status Join the chat at https://gitter.im/eliotsykes/rspec-rails-examples

An RSpec cheatsheet in the form of a Rails app. Learn how to expertly test Rails apps from a model codebase

A small yet comprehensive reference for developers who want to know how to test Rails apps using RSpec.

Here you'll find in-depth examples with detailed documentation explaining how to test with RSpec and related testing gems, which you can then apply to your own projects.

This application was originally written for the benefit of the developers I coach, who've found it a useful memory aid and catalyst for when they're learning RSpec. Now I'd like to get feedback from the wider community.

The repo contains examples of various spec types such as feature, mailer, and model. See the spec/ directory for all the example specs and types.

In the README below, you'll find links to some of the most useful cheatsheets and API documentation available for RSpec users.

See the well-commented files in the spec/support directory for walkthroughs on how to configure popular testing gems, such as DatabaseCleaner, Capybara, and FactoryGirl.

Hopefully this will be of help to those of you learning RSpec and Rails. If there's anything missing you'd like to see covered in the project, please submit your request via the issue tracker, I'd be happy to help โ€” Eliot Sykes

PS. Interested in growing your skills and supporting this project? Learn with the TDD Masterclass, get Test Coverage First Aid for your app, or grow with one-to-one coaching for Rails developers.


Support Configuration

The tests rely on this configuration being uncommented in spec/rails_helper.rb, you probably want it uncommented in your app too:

# Loads `.rb` files in `spec/support` and its subdirectories:
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }

(The rspec-rails installer generates this line, but it will be commented out.)

Run Specs in a Random Order

In a dependable, repeatable automated test suite, data stores (such as database, job queues, and sent email on ActionMailer::Base.deliveries) should return to a consistent state between each spec, regardless of the order specs are run in.

For a maintainable, predictable test suite, one spec should not set up data (e.g. creating users) needed by a later spec to pass. Each spec should look after its own test data and clear up after itself. (NB. If there is reference data that all tests need, such as populating a countries table, then this can go in db/seeds.rb and be run once before the entire suite).

The specs run in a random order each time the test suite is run. This helps prevent the introduction of run order and test data dependencies between tests, which are best avoided.

Random order test runs are configured using the config.order = :random and Kernel.srand config.seed options in spec/spec_helper.rb.

Testing Production Errors

When errors are raised, the Rails test environment may not behave as in production. The test environment may mask the actual error response you want to test. To help with this, you can disable test environment exception handling temporarily, spec/support/error_responses.rb provides respond_without_detailed_exceptions. See it in use in spec/api/v1/token_spec.rb to provide production-like error responses in the test environment.

Testing Rake Tasks with RSpec

RSpec testing Rake task configuration and example:

Pry-rescue debugging

pry-rescue can be used to debug failing specs, by opening pry's debugger whenever a test failure is encountered. For setup and usage see pry-rescue's README.

Time Travel Examples

ActiveSupport::Testing::TimeHelpers provides helpers for manipulating and freezing the current time reported within tests. These methods are often enough to replace the time-related testing methods that the timecop gem is used for.

TimeHelpers configuration how-to and examples:

ActiveJob Examples

ActiveJob::TestHelper provides help to test ActiveJob jobs.

ActiveJob::TestHelper configuration how-to and examples:

Database Cleaner Examples

Database Cleaner is a set of strategies for cleaning your database in Ruby, to ensure a consistent environment for each test run.

Database Cleaner configuration how-to:

Factory Girl Examples

Factory Girl is a library to help setup test data. factory_girl_rails integrates Factory Girl with Rails.

Factory Girl configuration how-to and examples:

VCR Examples

VCR records your test suite's HTTP interactions and replays them during future test runs. Your tests can run independent of a connection to external URLs. These HTTP interactions are stored in cassette files.

VCR configuration how-to and examples:

Capybara Examples

Capybara helps you write feature specs that interact with your app's UI as a user does with a browser.

Capybara configuration how-to and examples:

Puffing Billy Examples

Puffing Billy is like VCR for browsers used by feature specs. Puffing Billy is a HTTP proxy between your browser and external sites, including 3rd party JavaScript. If your app depends on JavaScript hosted on another site, then Puffing Billy will keep a copy of that JavaScript and serve it from a local web server during testing. This means tests dependent on that JavaScript will carry on working even if the original host cannot be connected to.

If you need to debug Puffing Billy, refer to its output in log/test.log.

Puffing Billy configuration how-to and examples:

Shoulda-Matchers Examples

Shoulda-matchers make light work of model specs.

shoulda-matchers configuration how-to and examples:

Email-Spec Examples

The "Subscribe to newsletter" feature was developed with help from email_spec

email_spec configuration how-to and examples:

Devise Examples

Specs testing registration, sign-in, and other user authentication features provided by Devise:

Custom Matchers

You can write your own custom RSpec matchers. Custom matchers can help you write more understandable specs.

Custom matchers configuration how-to and examples:

RSpec-Expectations Docs

RSpec-Mocks Specs & Docs

RSpec-Rails

See RSpec Rails for installation instructions.

Matchers

Generators

Feature Specs & Docs

API Request Specs, Docs, & Helpers

Mailer Specs & Docs

Controller Specs & Docs

View Specs & Docs

Helper Specs & Docs

Routing Specs & Docs

Validator Specs

To test a custom validator you've written, refer to these validator specs from other Rails projects. These specs each follow a similar pattern where the validator is tested with a dummy model that is defined and used within the spec only. Using a dummy model is usually preferable to writing a validator spec that is dependent on a real model.

Related task: Demonstrate Validator Specs within rspec-rails-examples

Enable Spring for RSpec

Spring is a Rails application preloader. It speeds up development by keeping your application running in the background so you don't need to boot it every time you run a new command.

To take advantage of this boost when you run bin/rspec, the spring-commands-rspec gem needs to be installed and a new rspec binstub needs to be created:

# 1. Add `spring-commands-rspec` to Gemfile in development and test groups and
#    install gem:
bundle install

# 2. Spring-ify the `bin/rspec` binstub:
bundle exec spring binstub rspec

# 3. Stop spring to ensure the changes are picked up:
bin/spring stop

# 4. Check bin/rspec is still working:
bin/rspec

See the spring-commands-rspec README for up-to-date installation instructions: https://github.com/jonleighton/spring-commands-rspec

Automated Continuous Integration with Travis CI

Continuous Integration (CI) is the practice of integrating new code into the master branch frequently, to help detect merge conflicts, bugs, and improve the quality of the software a development team writes.

CI is usually accompanied by running an application's test suite against the latest code changes, and flagging any test failures that are found. Developers are expected to investigate and fix these failures to maintain a passing test suite and therefore quality.

Travis CI is a build server that helps automate the CI process. Travis CI runs an application's tests against the latest changes pushed to the application's code respository. In this project, Travis CI runs the project's tests (rake test) on pull requests and on changes to the master branch.

Travis CI configuration how-to and example:


Contributors

rspec-rails-examples's People

Contributors

afomi avatar ambirdsall avatar andyw8 avatar chentsulin avatar ck3g avatar daniely avatar eliotsykes avatar gitter-badger avatar vinhnglx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rspec-rails-examples's Issues

Model associations specs

I was wondering if there was any chance of you fitting some associations into your spec examples somehow/somewhere so that we can see how best to handle specs for associations (has_many etc).

Thanks

Enforce spec file names have _spec.rb suffix

Specs without _spec.rb suffix will not be run by bare bin/rspec (no path)

# spec/support/spec_file_name_enforcer.rb
RSpec.configure do |config|
  config.before(:suite) do

    files_without_spec_suffix = Dir.glob('spec/**/*').select do |filename|
      File.file?(filename) && 
        !filename.match(/_spec\.rb\z/) &&
        !filename.match(%r{\Aspec/(support|factories|mailers/previews)/}) &&
        !filename.match(%r{\Aspec/(spec_helper\.rb|rails_helper\.rb|examples\.txt)\z})
    end

    if files_without_spec_suffix.any?
      raise 'Spec files need _spec.rb suffix: ' + files_without_spec_suffix.join(', ')
    end
  end
end

Complete test coverage for Devise-related functionality

Complete test coverage for Devise-related functionality:

TODO

  • unlock user
  • change password
  • forgot/reset password (click link on sign in page)
  • cancel registration? (there's a route for it)
  • resend confirmation instructions (click link on sign in page)
  • didn't receive unlock email (click link on sign in page)

DONE

  • sign in
  • sign out
  • register (happy path)
  • register (unhappy paths)
  • lock user

Demonstrate how to stub current_user in controller spec

E.g.

    it "..." do
      user = create(:user)
      foo = instance_double(Foo)
      foo_id = "123"

      allow(controller).to receive(:current_user).and_return(user)
      expect(user.foos).to receive(:find).with(foo_id).and_return(foo)
      expect(foo).to receive(:destroy).and_return(false)

      sign_in(user)

      delete :destroy, id: foo_id

      expect(flash[:error]).to eq("There was an error.")
    end

Add example for testing Rake tasks

Consider a rake subscriptions:confirmation_overdue:delete task that deletes unconfirmed subscriptions that have passed a confirmation deadline (e.g. created_at is > 3 days ago).

Puffing Billy - mkdir for cache path after configured

c.cache_path = "spec/support/http_cache/billy/"

Puffing Billy expects the developer to create the cache_path directory structure. If its not there it fails and logs an error to log/test.log. This error might be missed by a first-time user of puffing-billy.

Is there an option on Puffing Billy (latest version) to mkdir if it doesn't exist? Contribute?

If not, as part of puffing billy config, add a mkdir -p for the cache_path that runs immediately after its defined in spec/support/puffing_billy.rb.

Request Specs

First of all, I love this resource! I've learned a thing or two. I work a ton in Rails APIs and I noticed there wasn't anything on request specs. I noticed a bit of discussion around that. I can submit a PR that adds that but I want to make sure such a PR would be welcome.

Have request specs handle errors like production

Currently request specs that cause HTTP errors like 404 via RecordNotFound will raise exceptions instead of responding with 404.

Do one of these:

  • without_error_debugging (previously with_rails_error_handling) in a spec/support/error_helper.rb that is included with request specs: rails/rails#11289 (comment)
    OR
  • Comment out action_dispatch.show_exceptions = false in config/environments/test.rb and set action_dispatch.show_detailed_exceptions = true

Prefer without_error_debugging option used as needed in specs. The 2nd option may suppress useful error information in other tests.

List screen tests for searching / paging / sorting

I've looked through the specs in the repo but there doesn't appear to be anything along the lines of listing results that are searchable, sortable and offer paging.

I was wondering how best to set out / separate the specs for this and where the crossover may be between model specs for .search() and maybe controller specs for .page() and .sort() and any feature scenarios to check how they all hang together.

I thought it best to mention it as an issue on here rather than on stackoverflow in case it highlighted an omission from the repo.

Thanks

Add in reset_mailer call?

Check if reset_mailer is currently being called between examples. If not, add config to support/email_spec.rb to call reset_mailer before each example.

fill_in_epic_editor with Capybara + Selenium

# File: spec/support/epic_editor_helper.rb
module EpicEditorHelper

  def fill_in_epic_editor(text)
    # Epic Editor consists of:
    # - a parent iframe with id 'epiceditor-1234' where 1234 is random.
    # - a child iframe (within the parent iframe) with id 'epiceditor-editor-frame'.
    # - a contenteditable body (within the child iframe).

    # Use CSS attribute prefix selector (^=) to find iframe with id
    # beginning with 'epiceditor-' to match first parent iframe in page
    parent_iframe_node = find('iframe[id^=epiceditor-]')

    within_frame(parent_iframe_node) do
      child_iframe_id = 'epiceditor-editor-frame'
      within_frame(child_iframe_id) do
        find('body[contenteditable]').set(text)
      end
    end

  end

end

RSpec.configure do |config|
  config.include EpicEditorHelper, type: :feature
end

Usage in feature specs (must be js: true feature specs):

scenario "..." do
  fill_in_epic_editor "text goes here"
end

More comprehensive native date input support check

Bring in modernizr's date input support check (bug discovered by #70 investigations) to replace the date-input.js check rspec-rails-examples is using at time of writing.

The existing date-input.js check may not be working correctly in phantomjs 1.8.1 and 1.9.8.

Example of puffing-billy + VCR concurrent usage in same feature spec (Stripe checkout.js?)

Provide example spec for testing Stripe's checkout.js whilst also communicating with the Stripe API.

Include:

  • VCR to mock Stripe API calls direct from app
  • Puffing Billy to mock Stripe JavaScript in browser
  • js: true feature spec or choose puffing billy driver
  • Demonstrate within_frame ... for Stripe iframe
  • Work around buggy behaviour of stripe input fields with Capybara's fill_in. See fill_in_with_force/fill_in_stripe_field below and http://stackoverflow.com/a/26211723/67834
  ...

  within_frame 'stripe_checkout_app' do
    fill_in 'Email', with: '[email protected]'
    fill_in_stripe_field '#card_number', with: '4242424242424242'
    fill_in_stripe_field '#cc-exp', with: '12/22'
    fill_in 'CVC', with: '123'
    click_button 'Upgrade $9.99'
  end

  ...

  def fill_in_with_force(locator, options)
    page.execute_script "$('#{locator}').val('#{options[:with]}');"
  end

  alias_method :fill_in_stripe_field, :fill_in_with_force

  ...

Write and use refresh helper method to test AJAX-functionality

Used this refresh method on a project to ensure the page was always refreshed (IIRC, when the URL had a fragment identifier, e.g. http://localhost:3000/#/products, the refresh wouldn't work when it was a visit current_url, the refreshEnforcer random param was needed):

  def refresh
    url = URI.parse(current_url)
    if url.query.blank?
      url.query = ""
    else
      url.query << "&"
    end
    url.query << "refreshEnforcer=#{rand}"
    visit url.to_s
  end

Introduce this to rspec-rails-examples to test that an AJAX-dependent change has persisted.

Failure on native date input on subscribing user to newsletter

I'm on OSX 10.10.3, Firefox 38.0.5. It looks like the date input is not being recognized and falling back to today's date, which is not what the test is expecting.

$> rake
...snip...
Failures:

  1) Subscribe to newsletter in browser with native date input subscribes user to newsletter
     Failure/Error: expect(page).to be_confirm_subscription_page(Subscription.last)

       expected content: Your subscription will start on January 1st, 2015, thank you!
            got content: Your subscription will start on June 11th, 2015, thank you!
     # ./spec/features/subscribe_to_newsletter_spec.rb:21:in `block (4 levels) in <top (required)>'
     # ./spec/features/subscribe_to_newsletter_spec.rb:18:in `block (3 levels) in <top (required)>'

Finished in 32.53 seconds (files took 3.14 seconds to load)
73 examples, 1 failure

Failed examples:

rspec ./spec/features/subscribe_to_newsletter_spec.rb:7 # Subscribe to newsletter in browser with native date input subscribes user to newsletter

Randomized with seed 24965

/Users/lsmith/.rbenv/versions/2.2.2/bin/ruby -I/Users/lsmith/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib:/Users/lsmith/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.2.2/lib /Users/lsmith/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb failed
>$

Fix email_spec.rb duplicate :type key warnings

When running bin/rspec, these warnings are output:

rspec-rails-examples/spec/support/email_spec.rb:16: warning: duplicated key at line 16 ignored: :type
rspec-rails-examples/spec/support/email_spec.rb:17: warning: duplicated key at line 17 ignored: :type

Update to latest puffing-billy to use :selenium_chrome_billy driver

Most of these lines can be removed, the :selenium_chrome_billy driver is now available in puffing-billy since 0.5.1:

Capybara.register_driver :selenium_chrome_billy do |app|
Capybara::Selenium::Driver.new(
app, browser: :chrome,
switches: [
"--proxy-server=#{Billy.proxy.host}:#{Billy.proxy.port}"
# "--ignore-certificate-errors" # May be needed in future
]
)
end
Capybara.javascript_driver = :selenium_chrome_billy

Thanks @ronwsmith!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.