如何 DRY 测试相同 class 的相似方法的 RSpec 代码?

How to DRY an RSpec code that tests similar methods of the same class?

我有这样一段代码:

RSpec.describe CypherFileExecution do
  describe "self.drop_data_and_execute" do
    # (...)
    it "drops old data" do
      # (...)
    end
    it "executes cypher file" do
      described_class.drop_data_and_execute('spec/seeds/neo4j_object_spec.cypher')
      expect([
        does_object_exist_in_db?("relationship-class"),
        does_object_exist_in_db?("class-instance-class"),        
      ]).to eql [true, true]
    end
  end
  describe "self.execute" do
    it "executes cypher file" do
      described_class.execute('spec/seeds/neo4j_object_spec.cypher')
      expect([
        does_object_exist_in_db?("relationship-class"),
        does_object_exist_in_db?("class-instance-class"),        
      ]).to eql [true, true]
    end
  end
end

正如我们所见,"executes cypher file" 块对于两种方法都是相同的(事实上,其中一个调用另一个)。我该怎么做才能使此代码变干?如果我没记错的话,共享示例和上下文在 class 级别工作,但我这里有方法级别。我该怎么办?

这是 shared examples 的一个用例,我们可以将其与 subject 结合使用,利用 RSpec 的惰性求值。

RSpec.describe CypherFileExecution do
  shared_examples 'executes cypher file' do
    it "executes cypher file" do
      subject
      expect(does_object_exist_in_db?("relationship-class")).to be(true)
      expect(does_object_exist_in_db?("class-instance-class")).to be(true)
    end
  end

  describe "self.drop_data_and_execute" do
    subject { described_class.drop_data_and_execute('spec/seeds/neo4j_object_spec.cypher') }
    include_examples 'executes cypher file'

    # (...)
    it "drops old data" do
      # (...)
    end
  end

  describe "self.execute" do
    subject { described_class.execute('spec/seeds/neo4j_object_spec.cypher') }
    include_examples 'executes cypher file'
  end
end