Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何声明RSpec中示例之间共享的变量?_Ruby_Variables_Rspec - Fatal编程技术网

Ruby 如何声明RSpec中示例之间共享的变量?

Ruby 如何声明RSpec中示例之间共享的变量?,ruby,variables,rspec,Ruby,Variables,Rspec,假设我有以下规范: ... describe Thing do it 'can read data' do @data = get_data_from_file # [ '42', '36' ] expect(@data.count).to eq 2 end it 'can process data' do expect(@data[0].to_i).to eq 42 # Fails because @data is nil end end

假设我有以下规范:

...
describe Thing do

  it 'can read data' do
     @data = get_data_from_file  # [ '42', '36' ]
     expect(@data.count).to eq 2
  end

  it 'can process data' do
     expect(@data[0].to_i).to eq 42  # Fails because @data is nil
  end

end
...

我只想在给定的描述或上下文中共享一个变量。我会在一个例子中写一个值,在另一个例子中读它。如何做到这一点?

您应该在(:each)之前或(:all)之前使用
block:

describe Thing do
  before(:each) do
    @data = get_data_from_file  # [ '42', '36' ]
  end

  it 'can read data' do
    expect(@data.count).to eq 2
  end

  it 'can process data' do
    expect(@data[0].to_i).to eq 42
  end
end
区别在于,
before(:each)
将分别针对每种情况执行,而
before(:all)
将在本
description/context
中的所有示例之前执行一次。我建议您更喜欢(:each)
之前的
,而不是(:all)
之前的
,因为在这种情况下,每个示例都是孤立的,这是一种很好的做法

很少有情况下,您希望在(:all)
之前使用
,例如,如果您的
从\u文件中获取\u数据\u的执行时间较长,那么在这种情况下,您当然可以牺牲测试隔离来提高速度。但我想提醒您,当在(:all)
之前使用
时,在一个测试(
it
块)中修改
@data
变量将导致
descripe/context
范围内的其他测试出现意外后果,因为它们将共享该变量

before(:all)
示例:

describe MyClass do
  before(:all) do
    @a = []
  end

  it { @a << 1; p @a }
  it { @a << 2; p @a }
  it { @a << 3; p @a }
end
已更新

回答你的问题

describe MyClass do
  before(:all) do
    @a = []
  end

  it { @a = [1]; p @a }
  it { p @a }
end
将输出

[1]
[]
因为在第一个
it
中,您正在本地分配实例变量@a,所以它与
之前(:all)
块中的@a不同,并且对其他
it
块不可见,所以您可以通过输出
对象id
s来检查它。因此,只有修改才能起作用,赋值将导致新对象的创建


所以,如果您多次赋值变量,您可能会得到一个
it
块和多个期望值

这正是的目的,它允许您使用代码执行此操作:

...
describe Thing do
  let(:data) { get_data_from_file }

  it 'can read data' do
     expect(data.count).to eq 2
  end

  it 'can process data' do
     expect(data[0].to_i).to eq 42
  end

end
...

我也遇到了同样的问题。我是如何用工厂女孩宝石解决的

以下是基本知识:

创建工厂(以下是代码片段:

require 'factory_girl'
require 'faker' # you can use faker, if you want to use the factory to generate fake data

FactoryGirl.define do
  factory :generate_data, class: MyModule::MyClass do
    key 'value'
  end
end
现在,在制作工厂后,您需要制作一个如下所示的模型:

Module MyModule
  class MyClass
    attr_accessor :key

    #you can also place methods here to call from your spec test, if you wish
    # def self.test
        #some test
    # end
  end
end
describe Thing do
  before(:all) do
  @data = FactoryGirl.build(:generate_data)
  end

  it 'can read data' do
     @data.key = get_data_from_file  # [ '42', '36' ]
     expect(@data.key.count).to eq 2
  end

  it 'can process data' do
     expect(@data.key[0].to_i).to eq 42  # @data will not be nil. at this point. whatever @data.key is equal to last which was set in your previous context will be what data.key is here
  end

end
现在回到您的示例,您可以执行以下操作:

Module MyModule
  class MyClass
    attr_accessor :key

    #you can also place methods here to call from your spec test, if you wish
    # def self.test
        #some test
    # end
  end
end
describe Thing do
  before(:all) do
  @data = FactoryGirl.build(:generate_data)
  end

  it 'can read data' do
     @data.key = get_data_from_file  # [ '42', '36' ]
     expect(@data.key.count).to eq 2
  end

  it 'can process data' do
     expect(@data.key[0].to_i).to eq 42  # @data will not be nil. at this point. whatever @data.key is equal to last which was set in your previous context will be what data.key is here
  end

end

无论如何,如果您有其他解决方案,祝您好运!谢谢。我的想法是,我想在一个示例中设置一个变量,并在同一个“描述”或“上下文”块中在另一个示例中读取/更新它。由于某些原因,您提出的解决方案不起作用。@AndreyEsperanza您以前是否尝试过
(:all)
?是的。当然,我给出了一个过于简化的示例。现在我正在找出真正的规范可能有什么问题。@AndreyEsperanza我刚刚测试了并在我的答案中添加了相应的示例。也许你应该向我们展示你的代码。你的示例是有效的,但这不是我需要的。这个怎么样:
it{@a=[1]};it{p@a}[],而不是[1]
感谢您的回答,但正如您从上面的问题中看到的,我们的想法是在同一个“描述”或“上下文”块中,在一个示例中设置一个变量,并在另一个示例中读取/更新它。