Skip to content

Repository files navigation

Testing Rails with RSpec

Beginners introduction to testing Ruby On Rails application with RSpec and Capybara.

Install Rails with RSpec (v0.1)

  1. Install rails without minitest: rails new rails-rspec-tutorial -T;

  2. Add rspec to Gemfile:

group:development,:testdogem'rspec-rails','~> 3.7'end
  1. Install dependencies: bundle install;

  2. Execute bundle exec rails generate rspec:install to create a /spec dir;

  3. Run rspec: bundle exec rspec

Your first spec (v0.2)

  1. Create first spec:
require"rails_helper"RSpec.describe"hello spec"dodescribe"math"doexpect(6 * 7).toeq(43)endend
  1. And catch an error:

Failures:
1) hello spec math should be able to perform basic math
Failure/Error: expect(6 * 7).to eq(43)
expected: 43
got: 42
  1. Fix the error to get test passed:
require"rails_helper"RSpec.describe"hello spec"dodescribe"math"doit"should be able to perform basic math"do# expect(6 * 7).to eq(43) # => falseexpect(6 * 7).toeq(42)endendend
  1. Add another spec with empty string:
require"rails_helper"RSpec.describe"hello spec"do# ...describeStringdolet(:string){String.new}it"should provide an empty string"doexpect(string).toeq("")endendend

Create a unit test for Article model (v0.3)

  1. Create model Article:
bundle exec rails g model Article title:string body:text active:boolean
RAILS_ENV=test bundle exec rake db:migrate
  1. Create spec/models/article_spec.rb:
require"rails_helper"RSpec.describeArticle,type: :modeldocontext"validations tests"doit"ensures the title is present"doarticle=Article.new(body: "Content of the body")expect(article.valid?).toeq(false)endit"ensures the body is present"doarticle=Article.new(title: "Title")expect(article.valid?).toeq(false)endit"ensures the article is active by default"doarticle=Article.new(body: "Content of the body",title: "Title")expect(article.active?).toeq(true)endit"should be able to save article"doarticle=Article.new(body: "Content of the body",title: "Title")expect(article.save).toeq(true)endendcontext"scopes tests"doendend
  1. Add some presence validators to app/models/article.rb:
classArticle < ApplicationRecordvalidates_presence_of:title,:bodyend
  1. Create a migration:
classMakeArticleActiveByDefault < ActiveRecord::Migration[5.1]defchangechange_column:articles,:active,:boolean,default: trueendend
  1. Run migration:
bundle exec rake db:migrate
  1. Add scope specs:
require"rails_helper"RSpec.describeArticle,type: :modeldo# ...context"scopes tests"dolet(:params){{body: "Content of the body",title: "Title",active: true}}before(:each)doArticle.create(params)Article.create(params)Article.create(params)Article.create(params.merge(active: false))Article.create(params.merge(active: false))endit"should return all active articles"doexpect(Article.active.count).toeq(3)endit"should return all inactive articles"doexpect(Article.inactive.count).toeq(2)endendend

Create functional test for Articles controller (v0.4)

  1. Create Articles controller scaffold:
bundle exec rails g scaffold_controller Articles
rm -rf spec/views spec/routing spec/request spec/helpers spec/requests
  1. Create Articles spec:
require"rails_helper"RSpec.describeArticlesController,type: :controllerdocontext"GET #index"doit"returns a success response"doget:index# expect(response.success).to eq(true)expect(response).tobe_successendendcontext"GET #show"dolet!(:article){Article.create(title: "Test title",body: "Test body")}it"returns a success response"doget:show,params: {id: article}expect(response).tobe_successendendend
  1. Add articles to routes.rb file:
Rails.application.routes.drawdoresources:articlesend
  1. Add --format documentation to .rspec

Create integration spec and a home page (v0.5)

  1. Add Capybara to Gemfile:
group:development,:testdo# Call 'byebug' anywhere in the code to stop execution and get a debugger consolegem'byebug',platforms: [:mri,:mingw,:x64_mingw]gem'rspec-rails','~> 3.7'gem'capybara'end
  1. Add these lines to your spec/rails_helper.rb file:
require'capybara/rails'require'capybara/rspec'
  1. Create first feature test by running bundle exec rails g rspec:feature home_page:
require"rails_helper"RSpec.feature"Visiting the homepage",type: :featuredoscenario"The visitor should see a welcome message"dovisitroot_pathexpect(page).tohave_text("Welcome to my blog!")endend
  1. Add root to routes.rb:
Rails.application.routes.drawdoroot"home#index"resources:articlesend
  1. Generate controller:
bundleexecrailsgcontrollerHomeindexrm -rfspec/controllers/home_controller_spec.rbspec/views/homespec/views/home/index.html.erb_spec.rbspec/helpers/home_helper_spec.rb
  1. Modify the view app/views/home/index.html.erb:
<h1>Welcome to my blog!</h1><p>Find me in app/views/home/index.html.erb</p>

Create integration spec for Articles v0.6

  1. bundle exec rails g rspec:feature articles

  2. Create feature spec:

require'rails_helper'RSpec.feature"Articles",type: :featuredocontext"Create new article"doscenario"Should be successful"dovisitnew_article_pathwithin("form")dofill_in"Title",with: "Test title"fill_in"Body",with: "Test body"check"Active"endclick_button"Create Article"expect(page).tohave_content("Article successfully created")endscenario"Should fail"doendendcontext"Update article"doendcontext"Remove existing article"doendend
  1. Fix the view (app/views/articles/_form.erb):
<%= form_with(model: article, local: true) do |form| %><% if article.errors.any? %><divid="error_explanation"><h2><%=pluralize(article.errors.count,"error")%> prohibited this article from being saved:</h2><ul><%article.errors.full_messages.eachdo |message| %><li><%=message%></li><%end%></ul></div><%end%><div><%=form.label:title%><%=form.text_field:title,id: "article_title"%></div><div><%=form.label:body%><%=form.text_area:body,id: "article_body"%></div><div><%=form.label:active%><%=form.check_box:active,id: "article_active"%></div><divclass="actions"><%=form.submit%></div><%end%>
  1. Allow attributes in app/controllers/articles_controller.rb:
defarticle_paramsparams.require(:article).permit(:active,:id,:title,:body)end
  1. Full Articles test:
require'rails_helper'RSpec.feature"Articles",type: :featuredocontext"Create new article"dobefore(:each)dovisitnew_article_pathwithin("form")dofill_in"Title",with: "Test title"check"Active"endendscenario"should be successful"dofill_in"Body",with: "Test body"click_button"Create Article"expect(page).tohave_content("Article was successfully created")endscenario"should fail"doclick_button"Create Article"expect(page).tohave_content("Body can't be blank")endendcontext"Update article"dolet(:article){Article.create(title: "Test title",body: "Test content")}before(:each)dovisitedit_article_path(article)endscenario"should be successful"dowithin("form")dofill_in"Body",with: "New body content"endclick_button"Update Article"expect(page).tohave_content("Article was successfully updated")endscenario"should fail"dowithin("form")dofill_in"Body",with: ""endclick_button"Update Article"expect(page).tohave_content("Body can't be blank")endendcontext"Remove existing article"dolet!(:article){Article.create(title: "Test title",body: "Test content")}scenario"remove article"dovisitarticles_pathclick_link"Destroy"expect(page).tohave_content("Article was successfully destroyed")expect(Article.count).toeq(0)endendend

Add Selenium web driver (v0.7):

  1. Add to Gemfile:
group:development,:testdo# Call 'byebug' anywhere in the code to stop execution and get a debugger consolegem'byebug',platforms: [:mri,:mingw,:x64_mingw]gem'rspec-rails','~> 3.7'gem'capybara'gem'selenium-webdriver'end
  1. Add to spec/rspec_helper.rb:
Capybara.default_driver=:selenium_chrome_headless
  1. Fix articles spec:
context"Remove existing article"dolet!(:article){Article.create(title: "Test title",body: "Test content")}scenario"remove article"dovisitarticles_pathexpect(Article.count).toeq(1)accept_alertdoclick_link"Destroy"endexpect(page).tohave_content("Article was successfully destroyed")expect(Article.count).toeq(0)endend

Add simplecov gem (v0.8):

  1. Rails coverage report: bundle exec rails stats

  2. To install codecov add to your Gemfile:

gem'simplecov',require: false,group: :test
  1. Add to your spec/rails_helper.rb:
require'simplecov'SimpleCov.start
  1. Don't forget to add coverage/ dir to your .gitignore file;

Helpful links:

About

Beginners introduction to testing Ruby On Rails application with RSpec and Capybara

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages