在邁克爾哈特爾的Ruby On Rails教程中,作者在撰寫集成測試以驗證其註冊頁面的部分,他使用了代碼spinet下圖。我得到了代碼的功能,但卻無法理解'如何'部分,即無法理解執行順序。RSpec如何在ROR中工作
expect { click_button "Create my account" }.not_to change(User, :count)
有人可以請解釋上述方法和塊的鏈的語義,以及它們如何組合在一起?
在邁克爾哈特爾的Ruby On Rails教程中,作者在撰寫集成測試以驗證其註冊頁面的部分,他使用了代碼spinet下圖。我得到了代碼的功能,但卻無法理解'如何'部分,即無法理解執行順序。RSpec如何在ROR中工作
expect { click_button "Create my account" }.not_to change(User, :count)
有人可以請解釋上述方法和塊的鏈的語義,以及它們如何組合在一起?
你會使用expect ... change
來驗證一個特定的方法調用的變化 - 或不改變 - 一些其他的價值。在這種情況下:
expect { click_button "Create my account" }.not_to change(User, :count)
會導致RSpec的做到以下幾點:
User.count
並注意返回的值。 (這可以在例如被指定爲接收器和方法名,像(User, :count)
,或者作爲代碼的任意塊,像{ User.count }
。click_button "Create my account"
其是水豚方法模擬鏈路上的鼠標點擊。User.count
再次使用expect ... change
其他方式:。
expect { thing.destroy }.to change(Thing, :count).from(1).to(0)
expect { thing.tax = 5 }.to change { thing.total_price }.by(5)
expect { thing.save! }.to raise_error
expect { thing.symbolize_name }.to change { thing.name }.from(String).to(Symbol)
一些文檔是here。
它是如何做到這一點有點神祕,並沒有必要了解它是如何工作的,以便使用它。對expect
的調用正在使用rspec自己的定製DSL和「匹配器」系統定義rspec執行的結構。加里伯恩哈特有一個相當整潔的screencast,其中他認爲rspec的奧祕實際上自動從一個動態的語言,如紅寶石掉落。使用 rspec並不是的一個很好的介紹,但如果你對它的工作原理感到好奇,你可能會覺得它很有趣。
UPDATE
看到另一個回答您的評論後,我將添加有關操作的整理了一下。不直觀的技巧是執行所有塊的匹配器(在這種情況下爲change
)。 expect
有一個lambda,not_to
是should_not
的別名,其作用是將lambda傳遞給匹配器。在這種情況下,匹配器是change
,它知道一次執行自己的參數,然後執行它傳遞的lambda(expect
中的那個),然後再次運行自己的參數以查看是否發生了變化。這很棘手,因爲該行看起來應該從左到右執行,但由於大部分代碼只是傳遞代碼塊,因此它們可以將它們混合成匹配器最有意義的順序。
我不是rspec內部專家,但這是我對基本想法的理解。
我曾閱讀過最詳細,最有用的答案。如果可以的話,我會贊成這個100倍。謝謝! –
下面是從Ryan Bates Railscast on Request Specs and Capybara
require 'spec_helper'
describe "Tasks" do
describe "GET /tasks" do
it "displays tasks" do
Task.create!(:name => "paint fence")
visit tasks_path
page.should have_content("paint fence")
end
end
describe "POST /tasks" do
it "creates a task" do
visit tasks_path
fill_in "Name", :with => "mow lawn"
click_button "Add"
page.should have_content("Successfully added task.")
page.should have_content("mow lawn")
end
end
end
摘錄下面是從the docs on RSPec Expectations
describe Counter, "#increment" do
it "should increment the count" do
expect{Counter.increment}.to change{Counter.count}.from(0).to(1)
end
# deliberate failure
it "should increment the count by 2" do
expect{Counter.increment}.to change{Counter.count}.by(2)
end
end
所以基本上的摘錄中,
expect { click_button "Create my account" }.not_to change(User, :count)
是部分RSpec的:
expect {...}.not_to change(User, :count)
和一部分水豚
click_button "Create my account"
(這裏是a link to the Capyabara DSL - 您可以搜索click_button
)
這聽起來像你正在尋找與他們兩人的總例子。這不是一個很好的例子,但它可能是這個樣子:
describe "Tasks" do
describe "GET /tasks" do
it "displays tasks" do
expect { click_button "Create my account" }.not_to change(User, :count)
end
end
end
Tnx爲好例子。我更感興趣的是知道表達式的語義,比如劑量'change(..)'如何執行兩次以及執行的總體順序。 – Bedasso
這不是水豚,它是RSpec。 –
@RyanBigg謝謝,剛剛糾正它。 – Bedasso