All of my tests consistently pass when simply running rspec. I've installed Guard and now I get inconsistencies. Specifically, if I make a change to a controller, its spec might get 1 failure, or 3, or 6. They seem to be rooted in a database lock that causes the other tests to use inconsistent data.
I've tried to find similar problems but all I'm coming up with are rspec and sqlite solutions. I'm confident it is a Guard config problem since, as I said, the tests run from command line.
Here's an example of when I made a couple changes in the same file and got different results each time:
]2;[RSpec results] Failed
10:20:05 - INFO - Running: spec/controllers/V1/players_controller_spec.rb
..
An error occurred in an after hook
ActiveRecord::StatementInvalid: SQLite3::IOException: disk I/O error: DELETE FROM "player_connections"
occurred at /Users/joe/.rvm/gems/ruby-2.1.1/gems/sqlite3-1.3.9/lib/sqlite3/statement.rb:108:in `step'
F...
Failures:
1) V1::PlayersController GET players with failing auth fails when incorrect token is passed
Failure/Error: FactoryGirl.create :client, name: "joe", auth_token: "bad token!!"
ActiveRecord::StatementInvalid:
SQLite3::SQLException: cannot rollback - no transaction is active: rollback transaction
# ./spec/controllers/V1/players_controller_spec.rb:14:in `block (3 levels) in <top (required)>'
Finished in 1.26 seconds (files took 4.33 seconds to load)
6 examples, 1 failure
Failed examples:
rspec ./spec/controllers/V1/players_controller_spec.rb:13 # V1::PlayersController GET players with failing auth fails when incorrect token is passed
Randomized with seed 45348
]2;[RSpec results] Failed
10:24:38 - INFO - Running: spec/controllers/V1/players_controller_spec.rb
FF..F.
Failures:
1) V1::PlayersController POST player should default score to 0
Failure/Error: post :create, format: :json, player: FactoryGirl.attributes_for(:player)
ActiveRecord::StatementInvalid:
SQLite3::SQLException: cannot rollback - no transaction is active: rollback transaction
# ./app/controllers/v1/players_controller.rb:18:in `create'
# ./spec/controllers/V1/players_controller_spec.rb:59:in `block (3 levels) in <top (required)>'
2) V1::PlayersController POST player should create a new player
Failure/Error: let!(:client) { FactoryGirl.create :client, name: "joe", auth_token: "asdfasdfasdfasdfasdfasdf" }
ActiveRecord::StatementInvalid:
SQLite3::SQLException: cannot rollback - no transaction is active: rollback transaction
# ./spec/controllers/V1/players_controller_spec.rb:50:in `block (3 levels) in <top (required)>'
3) V1::PlayersController GET players with failing auth fails when no token exists in client record
Failure/Error: FactoryGirl.create :client, name: "joe"
ActiveRecord::StatementInvalid:
SQLite3::SQLException: cannot rollback - no transaction is active: rollback transaction
# ./spec/controllers/V1/players_controller_spec.rb:21:in `block (3 levels) in <top (required)>'
Finished in 0.61151 seconds (files took 3.81 seconds to load)
6 examples, 3 failures
Failed examples:
rspec ./spec/controllers/V1/players_controller_spec.rb:57 # V1::PlayersController POST player should default score to 0
rspec ./spec/controllers/V1/players_controller_spec.rb:52 # V1::PlayersController POST player should create a new player
rspec ./spec/controllers/V1/players_controller_spec.rb:20 # V1::PlayersController GET players with failing auth fails when no token exists in client record
Randomized with seed 5752
]2;[RSpec results] 6 examples, 3 failures in 0.6115 seconds
ain)>
I think my Guardfile is just the example that comes when you init guard:
require 'active_support/inflector'
# A sample Guardfile
# More info at https://github.com/guard/guard#readme
# Note: The cmd option is now required due to the increasing number of ways
# rspec may be run, below are examples of the most common uses.
# * bundler: 'bundle exec rspec'
# * bundler binstubs: 'bin/rspec'
# * spring: 'bin/rsspec' (This will use spring if running and you have
# installed the spring binstubs per the docs)
# * zeus: 'zeus rspec' (requires the server to be started separetly)
# * 'just' rspec: 'rspec'
guard :rspec, cmd: 'bundle exec rspec' do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
# Rails example
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
watch('config/routes.rb') { "spec/routing" }
watch('app/controllers/application_controller.rb') { "spec/controllers" }
watch('spec/rails_helper.rb') { "spec" }
# Capybara features specs
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
# Turnip features and steps
watch(%r{^spec/acceptance/(.+)\.feature$})
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
end
Including spec file:
describe V1::PlayersController, type: :controller do
before :each do
controller.request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials('asdfasdfasdfasdfasdfasdf')
end
after :each do
ActiveRecord::Base.subclasses.each(&:delete_all)
end
describe "GET players with failing auth" do
it 'fails when incorrect token is passed' do
FactoryGirl.create :client, name: "joe", auth_token: "bad token!!"
get :index, format: :json
expect(response).not_to be_successful
end
it 'fails when no token exists in client record' do
FactoryGirl.create :client, name: "joe"
get :index, format: :json
expect(response).not_to be_successful
end
end
describe "GET players with proper auth" do
let!(:player_before_transact_points) { FactoryGirl.create :player, name: "Sam", default_pull_rate: 105 }
let!(:player_2) { FactoryGirl.create :player, name: "Ma", default_pull_rate: 125 }
let!(:client) { FactoryGirl.create :client, name: "joe", auth_token: "asdfasdfasdfasdfasdfasdf" }
it "is authenticated" do
get :index, format: :json
expect(response).to be_successful
end
it "returns all players" do
get :index, format: :json
body = JSON.parse(response.body)
power_up_names = body.map { |m| m["name"] }
expect(power_up_names).to match_array(["Sam", "Ma"])
end
end
describe "POST player" do
let!(:client) { FactoryGirl.create :client, name: "joe", auth_token: "asdfasdfasdfasdfasdfasdf" }
it "should create a new player" do
expect { post :create, format: :json, player: FactoryGirl.attributes_for(:player) }.to change(V1::Player, :count).by(1)
end
it "should default score to 0" do
post :create, format: :json, player: FactoryGirl.attributes_for(:player)
expect(V1::Player.last.score).not_to be_nil
expect(V1::Player.last.score).to eq 0
end
end
end