A Ruby on Rails configuration for RSpec Capybara testing with a postgres database.
rails new capyspecpsql -d postgres -T
Gemfile
.rspec
spec_helper.rb
rails_helper.rb
group :development, :test do
gem 'rspec-rails', '~> 3.8', '>= 3.8.2'
gem 'faker', '~> 1.9', '>= 1.9.3'
gem 'factory_bot_rails', '~> 5.0', '>= 5.0.2'
end
group :development do
# rest ommitted
gem 'spring-commands-rspec', '~> 1.0', '>= 1.0.4' # faster app boot time
end
group :test do
gem 'database_cleaner', '~> 1.7'
gem 'capybara', '~> 3.22'
end
--color
--require spec_helper
--format doc
config.order = :random # runs test cases in random order
Kernel.srand config.seed # to replicate exact test order
require 'database_cleaner' # eliminates dependencies by cleans database between specs
require 'capybara/rspec'
RSpec.configure do |config|
# truncation prefered strategy with JS test cases
config.use_transaction_fixtures = false
# use truncation to clean before each suite:
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
# use truncation before each test for JS, transaction otherwise
config.before(:each) do |example|
DatabaseCleaner.strategy = example.metadata[:js] ? :truncation : :transaction
end
# clean db after each spec
config.after(:each) do
DatabaseCleaner.clean
end
end
If the following warning occurs after executing rspec .
You must use Bundler 2 or greater with this lockfile.
Try the following command and run rspec .
again:
gem install bundler && bundler update --bundler
config.generators do |g|
g.test_framework :rspec,
:fixtures => true, # generate a fixture for each model
:view_specs => false,
:helper_specs => false,
# omits spec file for routes.rb:
:routing_specs => false, # switch if app grows
:controller_specs => true,
:request_specs => true
# generate factories instead of fixtures with target save dir
g.fixture_replacement :factory_bot, :dir => "spec/factories"
end
$ rails g scaffold Album title:string
$ rails db:migrate RAILS_ENV=test
$ bundle exec spring binstub rspec
album_spec.rb
require 'rails_helper'
RSpec.describe Album do
#let(:album) {Album.new}
subject { Album.new }
it 'is not valid without a title' do
expect(subject).not_to be_valid
end
it 'is not valid without a title longer than 100 chars' do
subject.title = 'a' * 101
expect(subject).not_to be_valid
end
it 'is valid with proper data' do
subject.title = 'a' * 50
expect(subject).to be_valid
end
end
album.rb
class Album < ApplicationRecord
validates :title, presence: true,
length: { maximum: 100 }
end
$ rspec .
$ rails g model Album title:string
$ rails db:migrate RAILS_ENV=test
$ bundle exec spring binstub rspec
album_spec.rb
require 'rails_helper'
RSpec.describe Album do
#let(:album) {Album.new}
subject { Album.new }
it 'is not valid without a title' do
expect(subject).not_to be_valid
end
it 'is not valid without a title longer than 100 chars' do
subject.title = 'a' * 101
expect(subject).not_to be_valid
end
it 'is valid with proper data' do
subject.title = 'a' * 50
expect(subject).to be_valid
end
end
album.rb
class Album < ApplicationRecord
validates :title, presence: true,
length: { maximum: 100 }
end
$ rails db:migrate RAILS_ENV=test && rspec .
index_spec.rb
require 'rails_helper'
RSpec.feature 'Albums list' do # RSpec.describe '', type: :feature
scenario 'unauthenticated user' do # alias for it method
visit albums_path
within '#content' do
expect(find('h1')).to have_content('Albums')
end
# expect(find('#content h1')).to have_content('Albums')
# to use xpath instead of css do: find(:xpath, 'foo')
end
end
albums_controller.rb
class AlbumsController < ApplicationController
def index
end
end
app/views/albums/index.html.erb
<h1>Albums</h1>
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rorspec</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<div id="content">
<%= yield %>
</div>
</body>
</html>
routes.rb
Rails.application.routes.draw do
resources :albums, only: [:index]
root to: 'albums#index'
end
$ rails rspec .