RSpec PostgreSQL结果运行全部/单个测试不一致

时间:2018-09-03 08:09:30

标签: ruby-on-rails postgresql rspec

使用PostgreSQL数据库测试应用程序时遇到问题。在当前的设置中,我们将PostgreSQL用于生产环境,将SQLite3用于开发和测试环境。因为这可能导致意外行为,所以开发和测试环境需要切换到PostgreSQL。

切换测试环境是最困难的部分。在运行一个规格文件时,某些测试可以正常运行,但是在使用Guard一起运行所有测试时,则失败。在我的开发中手动运行测试时,其行为符合预期。

这是个例子。失败的测试是我切换到第二个用户并测试@items是否可以包含任何内容的最后一个测试。它返回一个空数组。

# /spec/controllers/materials_controller_spec.rb

describe MaterialsController do
  def create_users
    @user_1 = FactoryBot.create(:user)
    @user_2 = FactoryBot.create(:user)
    @admin = FactoryBot.create(:super_admin)

    @private_group = Group.find_or_create_by(name: "Private")
    @shared_group = Group.find_or_create_by(name: "Shared")
    @project_group = Group.find_or_create_by(name: "Project")

    @project = FactoryBot.create(:project)
    @user_1.projects << @project
    @user_2.projects << @project

    sign_in @user_1
  end

  def create_my_private_material
    @my_private_material = FactoryBot.create(:material, user: @user_1, group: @private_group, name: "Test01")
  end

  def create_my_private_material_2
    @my_private_material_2 = FactoryBot.create(:material, user: @user_1, group: @private_group)
  end

  def create_your_private_material
    @your_private_material = FactoryBot.create(:material, user: @user_2, group: @private_group)
  end

  def create_my_project_material
    @my_project_material = FactoryBot.create(:material, user: @user_1, group: @project_group, project: @project)
  end

  def create_your_shared_material
    @your_shared_material = FactoryBot.create(:material, user: @user_2, group: @shared_group)
  end

  def create_all_materials
    create_my_private_material
    create_my_private_material_2
    create_your_private_material
    create_my_project_material
    create_your_shared_material
  end

  describe "GET #index" do
    before do
      create_users
      create_all_materials
    end
    context "as material owner" do
      it "renders the index template" do
        get :index

        expect(assigns(:items)).to contain_exactly(@my_project_material, @my_private_material_2, @my_private_material)
        expect(response).to render_template("index")
      end
    end

    context "as being the owner and a current project set using the project scope" do
      before do
        @user_1.current_project_id = @project.id
        @user_1.save
      end
      it "should assing only the the materials the belong to the current project" do
        get :index, params: { scope: 'project' }
        expect(assigns(:items)).to contain_exactly(@my_project_material)
      end
    end

    context "as not being the material owner and no default project" do
      before do
        sign_out @user_1
        sign_in @user_2
      end
      it "filters out the materials based on group and project" do
        get :index
        expect(assigns(:items)).to contain_exactly(@your_private_material, @your_shared_material)
      end
    end

    context "as not being the owner, with a current project and using the project scope" do
      before do
        @user_2.current_project_id = @project.id
        @user_2.save
        sign_out @user_1
        sign_in @user_2
      end
      it "should assign only the materials the belong to the project" do
        get :index, params: { scope: 'project', project_id: @project.id }

        expect(assigns(:items)).to contain_exactly(@my_project_material)
      end
    end
  end

我已经进行了一些调试,发现了两件事:

  1. 运行所有测试时,测试中的错误是一致的。
  2. 在before块中添加DatabaseCleaner.clean_with :truncation时似乎可以修复某些测试。
  3. 将允许测试数据库的连接数更改为1确实适用于控制器测试,但是在我的功能测试中却是一个问题,因为它似乎至少需要连接。

因此,问题似乎与PostgreSQL数据库能够处理多个请求的优势有关。但是我不了解运行一个测试会通过,但是运行所有测试却会使某些测试失败。我已经在互联网上搜索了类似的相关问题,但是可以找到任何好的帖子或问题。

如果需要,我也可以发布失败的其他测试,但我认为这与同一个问题有关。

有什么建议吗?

0 个答案:

没有答案