首页 > 解决方案 > RSpec PostgreSQL 结果不一致运行所有/单个测试

问题描述

我在使用 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. 添加DatabaseCleaner.clean_with :truncationbefore 块似乎可以修复一些测试。
  3. 更改允许到测试数据库的连接数1确实适用于控制器测试,但在我的功能测试中是一个问题,因为它似乎至少需要连接。

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

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

有什么建议么?

标签: ruby-on-railspostgresqlrspec

解决方案


推荐阅读