как обектът работи в rspec в ruby ​​on rails

Наскоро научих за rspec тест в релси и след връзката https://relishapp.com/rspec/rspec-core/v/3-6/docs/subject/explicit-subject с кодът по-долу:

RSpec.describe Array do
  # This uses a context local variable. As you can see from the
  # specs, it can mutate across examples. Use with caution.
  element_list = [1, 2, 3]

  subject { element_list.pop }

  it "is memoized across calls (i.e. the block is invoked once)" do
    expect {
      3.times { subject }
    }.to change{ element_list }.from([1, 2, 3]).to([1, 2])
    expect(subject).to eq(3)
  end

  it "is not memoized across examples" do
    expect{ subject }.to change{ element_list }.from([1, 2]).to([1])
    expect(subject).to eq(2)
  end
end

Може ли някой да ми обясни:

  • защо 3.times { subject } се изпълнява само веднъж element_list.pop
  • изречението „това „не е запомнено в примери““ означаваше element_list все още [1, 2, 3], но в този пример е само [1, 2]?

Благодаря ти.


person Hung    schedule 28.05.2017    source източник


Отговори (1)


Първо, като пояснение, помощникът subject на RSpec не е нищо повече от специален случай на помощника let на RSpec. Използването на subject { element_list.pop } е еквивалентно на let(:subject) { element_list.pop }.

Както всеки друг let, subject се оценява веднъж за пример. Ако subject има стойност, тази стойност се връща без повторна оценка. Общият термин за това е "мемоизация".

Операторът ||= на Ruby прави същото. Той казва, "ако съществува стойност в тази променлива, върнете стойността, в противен случай оценете израза, присвоете го на променливата и върнете стойността." Можете да видите тази концепция в действие в конзолата с този пример:

>> element_list = [1, 2, 3]
>> subject ||= element_list.pop
=> 3
>> element_list
=> [1, 2]
>> subject ||= element_list.pop
=> 3
>> element_list
=> [1, 2]
>> subject
=> 3

Фактът, че subject не се мемоизира в примерите, означава, че стойността му се нулира, когато се изпълни нов пример. Така че за следващия ви блок it, subject ще започне без присвояване и изразът му ще бъде преоценен, когато бъде използван за първи път в следващия блок it.

person moveson    schedule 28.05.2017