2014-09-01 17 views
1

当简单运行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 
+0

用'rspec --order random'随机尝试运行测试我认为你所有的测试用例都相互依赖。这会导致此错误。测试用例之间不应该存在依赖关系。 – 2014-09-01 14:40:50

+0

我可能很幼稚,但我相信我已经制定了我的测试,使他们不依赖。我已经在上面添加了它们。从命令行显式运行随机似乎很好:'kate:dot_leech_api joe $ rspec --order random ............... 在1.24秒内完成(文件花了2.14秒加载) 15个例子,0失败 随机化的种子12409' – 2014-09-01 14:44:47

+0

我也观察到,在一个规范只有1个测试,有时我得到'QLite3 :: BusyException:数据库被锁定:INSERT INTO“player_connections”(“ (?,?,?,?)'和其他我得到了'ActiveRecord :: StatementInvalid: SQLite3 :: SQLException:无法回滚 - 没有事务处于活动状态:回滚事务' – 2014-09-01 14:54:13

回答

1

我有类似的问题,因为我不知道,我已经运行两个后卫的进程。所以确保只有一个进程正在访问数据库。

+0

这就是我..谢谢:) – 2015-08-27 09:49:53

相关问题