gpt4 book ai didi

ruby - Rspec it{} 评估使用最后一个变量值

转载 作者:太空宇宙 更新时间:2023-11-03 17:08:02 25 4
gpt4 key购买 nike

我正在使用 Rspec 为我的程序做一些测试。在规范中,我将类实例化一次,并使用describescontexts 对其执行测试。我遇到了一些有趣的事情,如果 its 似乎在上下文的末尾被评估。例如,给定以下类及其相关规范:

class Tmp
def initialize
@values = {}
end

def modify(new_value1, new_value2)
@values = {:a => new_value1, :b => new_value2}
end

def get_values
return @values
end
end

describe Tmp do
tmp = Tmp.new()

describe "testing something" do
context "change value" do

# First evaluation
tmp.modify("hi", "bye")
it {tmp.get_values.should == {:a => "hi", :b => "bye"}}

# Second evaluation
tmp.modify("bye", "hi")
it {tmp.get_values.should == {:a => "bye", :b => "hi"}}
end
end
end

使用提供的类和规范,结果如下:

F.

Failures:

1) Tmp testing something change value
Failure/Error: it {tmp.get_values.should == {:a => "hi", :b => "bye"}}
expected: {:a=>"hi", :b=>"bye"}
got: {:a=>"bye", :b=>"hi"} (using ==)
Diff:
@@ -1,3 +1,3 @@
-:a => "hi",
-:b => "bye"
+:a => "bye",
+:b => "hi"
# ./spec/tmp_spec.rb:11:in `block (4 levels) in <top (required)>'

Finished in 0.00211 seconds
2 examples, 1 failure

这很有趣,因为 Rspec 似乎使用 tmp 中的值评估第一个 it,因为它位于上下文的末尾。即使在上下文中 tmp 正在改变它的值并且应该通过,Rspec 也会根据变量在结束(我什至在 context 中用局部原始变量尝试过这个并且有类似的经历)。

有没有办法解决这个问题并按顺序评估its?或者至少让以下测试通过?我知道我可以使用不同的变量并且它会起作用,但必须有办法解决这个问题。我还想知道这是否是 Rspec 的预期效果。

更新菲利普的回答

通过在单个 it block 中进行更改,规范通过:

describe Tmp do
describe "do something" do
let(:instance) {Tmp.new}

it 'should be modifiable' do
instance.modify('hi', 'bye')
instance.values.should == {a: 'hi', b: 'bye'}
instance.modify('bye', 'hi')
instance.values.should == {a: 'bye', b: 'hi'}
end
end
end

但如果我使用主题,它似乎会返回并在第一个应该上失败

describe Tmp do
describe "do something" do
let(:instance) {Tmp.new}
subject{instance.values}

it 'should be modifiable' do
instance.modify('hi', 'bye')
should == {a: 'hi', b: 'bye'}
instance.modify('bye', 'hi')
should == {a: 'bye', b: 'hi'}
end
end
end

不知道为什么会这样。至少我看到更改应该在 it block 中以更好地反射(reflect)我们正在测试的更改。

最佳答案

您不应该在 itspecifybeforelet 之外创建实例和操作它们和 subject block 。否则主题和其他变量不会在测试后重置。

下面我使用几种不同的样式重写了您的规范。请参阅内联注释以获取解释。

class Tmp
# Exposes the @values ivar through #values
attr_reader :values

def initialize
@values = {}
end

def modify(new_value1, new_value2)
@values = {a: new_value1, b: new_value2}
end
end

describe Tmp do
#`let` makes the return value of the block available as a variable named `instance` (technically it is a method named instance, but let's call it a variable).
let(:instance) { described_class.new }

# Inside an it block you can access the variables defined through let.
it 'should be modifiable' do
instance.modify('hi', 'bye')
instance.values.should == {a: 'hi', b: 'bye'}
end

# or

# `specify` is like `it` but it takes no argument:
specify do
instance.modify('hi', 'bye')
instance.values.should == {a: 'hi', b: 'bye'}
end

# or

# This is another common way of defining specs, one describe per method.
describe '#modify' do
let(:instance) { described_class.new }
# Here we define the subject which is used implicitly when calling `#should` directly.
subject { instance.values }
before { instance.modify('hi', 'bye') }
it { should == {a: 'hi', b: 'bye' } # Equivalent to calling `subject.should == ...`
end

# or

# When we don't specify a subject, it will be an instance of the top level described object (Tmp).
describe '#modify' do
before { subject.modify('hi', 'bye') }
its(:values) { should == {a: 'hi', b: 'bye' }
end
end

关于ruby - Rspec it{} 评估使用最后一个变量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12539299/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com