RSpec 测试单独通过,但当 运行 一起时失败

RSpec tests pass in isolation, but fail when run together

在我的 code_controller_spec.rb 中,当我只是 运行 code_controller_spec.rb 中的测试时,我的测试通过了。但是,当我 运行 套件时,只有 createeditupdate 测试在 code_controller_spec.rb 内失败。我真的不知道从这里到哪里去,我真的不知道为什么当 运行 在一起时我的测试失败了。我有 config.use_transactional_fixtures = false 并且正在使用 database_cleaner。我的应用程序在本地通过以下操作运行良好,并且在创建或更新 post 时我没有收到任何错误。如果您需要更多信息,请告诉我。

当我运行套件时,我得到的失败是:

1) CodesController admin pages #create posts a new code post
     Failure/Error:
       post :create, params: {
         code: { 
           created_at: Date.today, 
           title: "Code things", 
           content: "The content of the code post",
           user_id: user.id
         }
       }

     ActionController::UrlGenerationError:
       No route matches {:action=>"create", :code=>{:created_at=>Fri, 20 Oct 2017, :title=>"Code things", :content=>"The content of the code post", :user_id=>1}, :controller=>"codes"}

2)  CodesController admin pages #edit edits a code post
     Failure/Error: get :edit, params: { id: code }

     ActionController::UrlGenerationError:
       No route matches {:action=>"edit", :controller=>"codes", :id=>#<Code id: 1, title: "Code post title", content: "Coding speak that not everyone can understand...", created_at: "2017-10-20 00:00:00", updated_at: "2017-10-21 06:05:27", user_id: 2>}

3) CodesController admin pages #update updates a code post
     Failure/Error: put :update, params: { id: code, code: code2 }

     ActionController::UrlGenerationError:
       No route matches {:action=>"update", :code=>{:title=>"Updated title", :content=>"Updated content"}, :controller=>"codes", :id=>#<Code id: 1, title: "Code post title", content: "Coding speak that not everyone can understand...", created_at: "2017-10-20 00:00:00", updated_at: "2017-10-21 06:05:27", user_id: 2>}

我的spec/controllers/user/codes_controller_spec.rb

RSpec.describe User::CodesController, type: :controller do

  let!(:user) { User.create(email: "user@example.com", password: "password") }
  let!(:code) { FactoryGirl.create(:code) }

  before do
    sign_in_as user
    expect(response).to have_http_status(:success)
  end

  describe "admin pages" do
    render_views

    context "#create" do
      it "posts a new code post" do
        post :create, params: {
          code: { 
            created_at: Date.today, 
            title: "Code things", 
            content: "The content of the code post",
            user_id: user.id
          }
        }
        expect(response).to redirect_to user_codes_path
        expect(flash[:success]).to eq "Post created successfully."
      end
    end

    context "#edit" do
      it "edits a code post" do
        get :edit, params: { id: code }
        expect(response).to render_template :edit
      end
    end

    context "#update" do
      let(:code2) do 
        { title: "Updated title", content: "Updated content" }
      end
      it "updates a code post" do
        put :update, params: { id: code, code: code2 }
        code.reload
        expect(response).to redirect_to user_code_path(code)
        expect(code.title).to eq code2[:title]
        expect(code.content).to eq code2[:content]
        expect(flash[:success]).to eq "Post updated successfully."
      end
    end
  end
end

我的spec/factories/post_factories.rb

FactoryGirl.define do
  factory :code do
    created_at Date.today
    title "Code post title"
    content "Coding speak that not everyone can understand..."

    association :user, factory: :user
  end

  factory :life do
    created_at Date.today
    title "Life post title"
    content "The world moves in mysterious ways; whether we want it to..."

    association :user, factory: :user
  end
end

I 运行 rspec --seed 123 --bisect 然后我 运行 输出,但我的所有测试都通过了。我应该提一下我是 --bisect.

的新手

这是 rspec --seed 123 --bisect 输出,当我 运行 这时我的所有测试都通过了。

rspec ./spec/controllers/user/codes_controller_spec.rb[1:1:1:1,1:1:2:1,1:1:3:1,1:1:4:1,1:1:5:1] ./spec/controllers/user/lives_controller_spec.rb[1:1:1,1:1:2] ./spec/features/admin_create_posts_spec.rb[1:1,1:2,1:3,1:4] ./spec/features/admin_edit_post_spec.rb[1:1,1:2,1:3] ./spec/features/clearance/user_signs_out_spec.rb[1:1] ./spec/features/clearance/visitor_resets_password_spec.rb[1:1,1:2,1:3,1:4,1:5,1:6] ./spec/features/clearance/visitor_signs_in_spec.rb[1:1,1:2,1:3,1:4,1:5,1:6,1:7,1:8] ./spec/features/clearance/visitor_signs_up_spec.rb[1:1,1:2,1:3,1:4,1:5,1:6,1:7,1:8] ./spec/features/clearance/visitor_updates_password_spec.rb[1:1,1:2,1:3] ./spec/features/homepage_spec.rb[1:1,1:2] ./spec/features/login_users_spec.rb[1:1,1:2] ./spec/features/logout_user_spec.rb[1:1] ./spec/features/showing_all_posts_spec.rb[1:1,1:2] ./spec/helpers/codes_helper_spec.rb[1:1] ./spec/helpers/lives_helper_spec.rb[1:1] ./spec/helpers/user/codes_helper_spec.rb[1:1] ./spec/helpers/user/lives_helper_spec.rb[1:1] ./spec/helpers/users_helper_spec.rb[1:1] ./spec/helpers/welcome_helper_spec.rb[1:1] ./spec/models/code_spec.rb[1:1] ./spec/models/life_spec.rb[1:1]

我的 database_cleaner 配置在 rails_helper.rb

require database_cleaner

RSpec.configure do |config|
  config.use_transactional_fixtures = false

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  # config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.before(:all) do
    FactoryGirl.reload
  end

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.

  config.before(:suite) do
    if config.use_transactional_fixtures?
      raise(<<-MSG)
        Delete line `config.use_transactional_fixtures = true` from rails_helper.rb (or set it to false) to prevent uncommitted transactions being used in JavaScript-dependent specs.
                During testing, the app-under-test that the browser driver connects to uses a different database connection to the database connection used by the spec. The app's database connection would not be able to access uncommitted transaction data setup over the spec's database connection.
      MSG
    end
    DatabaseCleaner.clean_with(:truncation)
  end  

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, type: :feature) do
    # :rack_test driver's Rack app under test shares database connection
    # with the specs, so continue to use transaction strategy for speed.
    driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test

    if !driver_shares_db_connection_with_specs
      # Driver is probably for an external browser with an app under test that does *not*
      # share a database connection with the specs, so use truncation strategy.
      DatabaseCleaner.strategy = :truncation
    end
  end

  # adds this from
  # 
  config.before(:each, truncation: true) do 
    Database::Cleaner.strategy = :truncation 
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.append_after(:each) do
    DatabaseCleaner.clean
  end
end

已更新 rails routes

的输出
Prefix Verb   URI Pattern                             Controller#Action
              root GET    /                                       welcome#index
         passwords POST   /passwords(.:format)                    clearance/passwords#create
      new_password GET    /passwords/new(.:format)                clearance/passwords#new
           session POST   /session(.:format)                      clearance/sessions#create
edit_user_password GET    /users/:user_id/password/edit(.:format) clearance/passwords#edit
     user_password PATCH  /users/:user_id/password(.:format)      clearance/passwords#update
                   PUT    /users/:user_id/password(.:format)      clearance/passwords#update
                   POST   /users/:user_id/password(.:format)      clearance/passwords#create
             users POST   /users(.:format)                        clearance/users#create
           sign_in GET    /sign_in(.:format)                      clearance/sessions#new
          sign_out DELETE /sign_out(.:format)                     clearance/sessions#destroy
                   GET    /sign_out(.:format)                     clearance/sessions#destroy
           sign_up GET    /sign_up(.:format)                      clearance/users#new
        user_lives GET    /user/lives(.:format)                   user/lives#index
                   POST   /user/lives(.:format)                   user/lives#create
     new_user_life GET    /user/lives/new(.:format)               user/lives#new
    edit_user_life GET    /user/lives/:id/edit(.:format)          user/lives#edit
         user_life GET    /user/lives/:id(.:format)               user/lives#show
                   PATCH  /user/lives/:id(.:format)               user/lives#update
                   PUT    /user/lives/:id(.:format)               user/lives#update
                   DELETE /user/lives/:id(.:format)               user/lives#destroy
        user_codes GET    /user/codes(.:format)                   user/codes#index
                   POST   /user/codes(.:format)                   user/codes#create
     new_user_code GET    /user/codes/new(.:format)               user/codes#new
    edit_user_code GET    /user/codes/:id/edit(.:format)          user/codes#edit
         user_code GET    /user/codes/:id(.:format)               user/codes#show
                   PATCH  /user/codes/:id(.:format)               user/codes#update
                   PUT    /user/codes/:id(.:format)               user/codes#update
                   DELETE /user/codes/:id(.:format)               user/codes#destroy
             lives GET    /lives(.:format)                        lives#index
              life GET    /lives/:id(.:format)                    lives#show
             codes GET    /codes(.:format)                        codes#index
              code GET    /codes/:id(.:format)                    codes#show

我认为这是一个自动加载问题。如果您的 ::CodesControllerUsers::CodesController 之前加载,那么您对 ​​Users::CodesController 的规范实际上使用的是 ::CodesController,因此无法创建正确的路线。当 运行 单独时,正确的 class 被自动加载并且一切正常。要解决此问题,需要在规范的开头使用正确的 class。

# spec/controllers/user/codes_controller_spec.rb

require 'user/codes_controller'
...

# spec/controllers/codes_controller_spec.rb

require 'codes_controller'
...