当简单运行rspec时,所有测试都一致通过。我已经安装了Guard,现在我得到了不一致。特别是,如果我对控制器进行了更改,其规格可能会失败1或3或6.它们似乎植根于导致其他测试使用不一致数据的数据库锁。使用SQLite进行警卫时出现不一致的事务异常
我试图找到类似的问题,但我想要的是rspec和sqlite解决方案。我相信这是一个Guard配置问题,正如我所说的,测试是从命令行运行的。
这里时,我在同一个文件一对夫妇的变化,每一次得到了不同的结果的一个例子:
]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)>
我想我Guardfile就是当你初始化自带的例子中后卫:
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
包括规范文件:
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
用'rspec --order random'随机尝试运行测试我认为你所有的测试用例都相互依赖。这会导致此错误。测试用例之间不应该存在依赖关系。 – 2014-09-01 14:40:50
我可能很幼稚,但我相信我已经制定了我的测试,使他们不依赖。我已经在上面添加了它们。从命令行显式运行随机似乎很好:'kate:dot_leech_api joe $ rspec --order random ............... 在1.24秒内完成(文件花了2.14秒加载) 15个例子,0失败 随机化的种子12409' – 2014-09-01 14:44:47
我也观察到,在一个规范只有1个测试,有时我得到'QLite3 :: BusyException:数据库被锁定:INSERT INTO“player_connections”(“ (?,?,?,?)'和其他我得到了'ActiveRecord :: StatementInvalid: SQLite3 :: SQLException:无法回滚 - 没有事务处于活动状态:回滚事务' – 2014-09-01 14:54:13