RSpec 中的夹具

Posted

技术标签:

【中文标题】RSpec 中的夹具【英文标题】:Fixtures in RSpec 【发布时间】:2012-07-25 22:12:18 【问题描述】:

我是使用 RSpec 在使用 mysql 数据库的 Rails 应用程序中编写测试的新手。我已经定义了我的固定装置,并将它们加载到我的规范中,如下所示:

before(:all) do
  fixtures :student
end

此声明是将我的夹具中定义的数据保存在学生表中,还是只是在测试运行时加载表中的数据并在所有测试运行后将其从表中删除?

【问题讨论】:

试试factory_girl或fabrication,而不是fixtures。 【参考方案1】:

如果您想在 RSpec 中使用fixture,请在 describe 块中指定您的 fixture,而不是在 before 块中:

describe StudentsController do
  fixtures :students

  before do
    # more test setup
  end
end

您的学生设备将被加载到学生表中,然后在每次测试结束时使用数据库事务回滚。

【讨论】:

relishapp.com/rspec/rspec-rails/docs/model-specs/…【参考方案2】:

首先:你不能在:all/:context/:suite hook中使用方法fixtures。不要尝试在这些钩子中使用固定装置(例如 post(:my_post))。

您只能在描述/上下文块中准备固定装置,就像 Infuse 之前写的那样。

打电话

fixtures :students, :teachers

不要将任何数据加载到数据库中!只需准备辅助方法studentsteachers。 当您第一次尝试访问所需的记录时,它们会延迟加载。之前

dan=students(:dan) 

这将以delete all from table + insert fixtures 方式加载学生和教师。

所以如果你在 before(:context) 钩子中准备了一些学生,他们现在就会消失了!!

在测试套件中只插入一次记录。

在测试套件结束时不会删除来自夹具的记录。它们会在下次测试套件运行时被删除并重新插入。

示例:

 #students.yml
   dan:
     name: Dan 
   paul:
     name: Paul

 #teachers.yml
    snape:
      name: Severus




describe Student do
  fixtures :students, :teachers
  
  before(:context) do
    @james=Student.create!(name: "James")
  end

  it "have name" do
   expect(Student.find(@james.id)).to be_present
   expect(Student.count).to eq 1
   expect(Teacher.count).to eq 0
  
   students(:dan)
   
   expect(Student.find_by_name(@james.name)).to be_blank
   expect(Student.count).to eq 2
   expect(Teacher.count).to eq 1
   
  end
end


#but when fixtures are in DB (after first call), all works as expected (by me)

describe Teacher do
  fixtures :teachers # was loaded in previous tests
  
  before(:context) do
    @james=Student.create!(name: "James")
    @thomas=Teacher.create!(name: "Thomas")
  end

  it "have name" do
   expect(Teacher.find(@thomas.id)).to be_present
   expect(Student.count).to eq 3 # :dan, :paul, @james
   expect(Teacher.count).to eq 2 # :snape, @thomas
  
   students(:dan)
      
   expect(Teacher.find_by_name(@thomas.name)).to be_present
   expect(Student.count).to eq 3
   expect(Teacher.count).to eq 2
   
  end
end

上述测试中的所有预期都将通过

如果这些测试再次运行(在下一个套件中)并按此顺序运行,则超出预期

 expect(Student.count).to eq 1

不会遇到! 将有 3 名学生(:dan、:paul 和新晋的@james)。 students(:dan) 之前的所有这些都将被删除,并且只会重新插入 :paul 和 :dan。

【讨论】:

是的!我找到了在所有测试之前加载所有固定装置的技巧。只需添加 RSpec.configure |config| config.global_fixtures= :all AND 直接在 spec_helper 中测试,它将尝试访问任何夹具。这样所有的灯具都会提前加载。【参考方案3】:

before(:all) 保留确切的数据,因为它被加载/创建一次。你做你的事,在测试结束时它会留下来。这就是为什么bui的链接有after(:all)来销毁或使用before(:each); @var.reload!;end从之前的测试中获取最新数据的原因。我可以看到在嵌套的 rspec 描述块中使用这种方法。

【讨论】:

以上是关于RSpec 中的夹具的主要内容,如果未能解决你的问题,请参考以下文章

Django - 夹具中的外键

如何将夹具中的不同 JSON 对象映射到 cypress 中的特定规范测试文件

如何将测试夹具传递给 C++ GTest 中的辅助函数

Golang 测试中的夹具

初始数据夹具中的用户

Rspec 不显示邮件正文中的内容