- Read Tutorial
This training guide assumes that you have already completed the Rails Foundations course, so we will not cover some of the basic fundamentals of the Ruby on Rails framework since I want the focus to be on building an application in the same way that you'd build one in a professional environment.
With that out of the way, let's get started!
The goal of this guide will be to:
- Run the app generator
- Configure the database
- Setup version control
- Integrate the RSpec and Capybara testing gems
Rails Application Generator
To begin, run the following command to create the application:
rails new dailysmarty -T --database=postgresql
Configure the database
This will create the application and bypass installing the default testing package. It will also set Postgres as the default database since I’m not really a fan of ever using SQLite since it can have some different behavior than Postgres, especially in regard to error forgiveness.
Now run rake db:create && rake db:migrate
to create the local database.
Setup version control
Wth that setup, let’s setup git version control, run:
git init git add . git ci -m 'initial commit'
Now let's create a remote repo on GitHub and add it as a remote
so we can push to it and eventually use it as the gateway for our deployment workflow (but more on that later).
You can see the repo here.
With that setup we can run:
git push
And our code is now live on our centralized GitHub repo.
RSpec Integration
Lastly for this step, let’s add the full RSpec testing suite. In addition to the rspec-rails
gem we’re also going to integrate:
- Capybara - this will let us create integration tests that will mimic user behavior and browser actions such as clicking on a link, filling out a form, etc.
- Database Cleaner - this helpful library will clean up our test database to protect us against spec errors such as records not getting created due to uniqueness validations.
- Factory Girl - with Factory Girl installed we can dynamically create sample database records and use them in our specs
I have a standard testing setup for the majority of applications I build and we're going to follow the same pattern (this will bring in three gems, if you want to see an implementation that only has RSpec you can checkout my RSpec tutorial. First, let's add in the Gems and group them in the correct Gem group (it wouldn't make sense to have the Gems available on production), I'm also going to clean up the entire Gemfile so it looks nice and clean. After you're done the Gemfile should look like this:
# Gemfile source 'https://rubygems.org' gem 'rails', '4.2.5' gem 'pg', '~> 0.15' gem 'sass-rails', '~> 5.0' gem 'uglifier', '>= 1.3.0' gem 'coffee-rails', '~> 4.1.0' gem 'jquery-rails' gem 'turbolinks' gem 'jbuilder', '~> 2.0' gem 'sdoc', '~> 0.4.0', group: :doc group :development, :test do gem 'byebug' gem 'rspec-rails', '~> 3.0' gem 'capybara' gem 'database_cleaner' end group :development do gem 'web-console', '~> 2.0' gem 'spring' end
I removed the comments and added the testing gems in the :development, :test
block:
gem 'rspec-rails', '~> 3.0' gem 'capybara' gem 'database_cleaner'
After running bundle
we will have access to the new testing libraries. Now let's run the RSpec
installer:
rails generate rspec:install
That will create our testing configuration files and setup the app's spec
directory. Let's customize the rails_helper.rb
file so that it will work with capybara
and DatabaseCleaner
:
# spec/rails_helper.rb ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) abort("The Rails environment is running in production mode!") if Rails.env.production? require 'spec_helper' require 'rspec/rails' require 'capybara/rails' ActiveRecord::Migration.maintain_test_schema! RSpec.configure do |config| config.fixture_path = "#{::Rails.root}/spec/fixtures" config.use_transactional_fixtures = false config.before(:suite) { DatabaseCleaner.clean_with(:truncation) } config.before(:each) { DatabaseCleaner.strategy = :transaction } config.before(:each, :js => true) { DatabaseCleaner.strategy = :truncation } config.before(:each) { DatabaseCleaner.start } config.after(:each) { DatabaseCleaner.clean } config.infer_spec_type_from_file_location! config.filter_rails_from_backtrace! end
If you compare the default rails_helper
file with what is above you'll see a few key changes:
I added a call to
capybara/rails
I updated the
use_transactional_fixtures
tofalse
I added a number of
DatabaseCleaner
configuration options
This should be all we need to do to get started. Let's run a quick test by creating a homepage and testing that the application can be reached in the browser. Create directory called features
and a file static
:
# spec/features/static_spec.rb require 'rails_helper' describe 'navigate' do describe 'homepage' do it 'can be reached successfully' do visit root_path expect(page.status_code).to eq(200) end end end
Running rspec
in the terminal will give us the error NameError: undefined local variable or method
root_path' for #RSpec::ExampleGroups::Navigate::Homepage:0x007fa73f05eef0:
We'll fix that by updating the routes.rb
file:
# config/routes.rb Rails.application.routes.draw do root to: 'static#home' end
Running the specs again we'd get another error because we don't have a static
controller, however it will still say that it doesn't recognize the root_path
, let's manually create the static controller:
# app/controllers/static_controller.rb class StaticController < ApplicationController end
Ok, if you run the specs again you'll get a different failure message, this time it will say AbstractController::ActionNotFound: The action 'home' could not be found for StaticController
.
Let's fix this by adding in the home
index action:
# app/controllers/static_controller.rb class StaticController < ApplicationController def home end end
Running the specs will now give us the error ActionView::MissingTemplate: Missing template static/home
, this is good, notice how we're progressively building the feature and the tests are walking us through the implementation? Now let's get it working by creating a new directory app/views/static
and adding a file: app/views/static/home.html.erb
.
Now let's run rspec
and watch our tests turn green.
It's a pretty good feeling, right? So let's discuss what is happening with this test:
Capybara is starting a mocked browser session
It's visiting the
root_path
It's checking to see if the
page
it visits has an HTTP status code of200
We'll get into much more comprehensive tests, however this proves that our application is functioning properly and that our test suite is configured properly and working.