TDD RSpec 水豚 Ruby Rails
TDD RSpec Capybara Ruby on Rails
我正在尝试熟悉 Capybara 和其他 TDD,但我失败了。我在这里的第一个例子(场景 "unsuccessfully post a message no user" do)应该是失败的,因为我没有输入用户,但无论如何它都会以某种方式输入,而不是收到预期的 "User must exist" 它说 "Welcome John" .我的 'before(:each)' 是否在它出现后仍会击中它,还是我有其他问题?
/spec/features/mess_spec.rb
require 'rails_helper'
feature "post message" do
scenario "unsuccessfully post a message no user" do
visit messages_path
fill_in "message[content]", with: "This is the content of my message."
click_button "Post a Message"
expect(page).to have_content "User must exist"
end
before(:each) do
visit new_user_path
fill_in "user[name]", with: "John"
click_button "Sign In"
visit messages_path
end
scenario "successfully post a message" do
fill_in "message[content]", with: "This is the content of my message."
click_button "Post a Message"
expect(page).to have_content "This is the content of my message"
expect(current_path).to eq(messages_path)
end
scenario "unsuccessfully post a message no content" do
fill_in "message[content]", with: ""
click_button "Post a Message"
expect(page).to have_content "Content is too short"
end
scenario "messages page should have a log out button" do
click_button "logout"
expect(current_path).to eq(new_user_path)
end
end
我的 spec/models/message_spec.rb 在第二次测试时遇到了类似的问题
it "should not save if no user" do
expect(build(:message)).to be_invalid
end
也没有失败,尽管我只是通过跳过工厂机器人来作弊所以这是我当前的工作文件
require 'rails_helper'
RSpec.describe Message, type: :model do
it "should save" do
expect(build(:message, user: build(:user))).to be_valid
end
it "should not save if no user" do
message = Message.new(
content: 'This is a message'
)
expect(message).to be_invalid
end
it "should not save content is too short" do
message = Message.new(
content: 'This',
user_id: '1'
)
expect(message).to be_invalid
end
end
您猜对了您的问题 - scenario
只是定义了测试 - 它没有定义测试的顺序,最佳做法实际上是 运行 您的测试以随机顺序确保您在各个测试之间没有任何耦合。这意味着在同一范围或更高范围内定义的任何 before(:each)
将在该范围内指定的每个 scenario
之前 运行。
要解决这个问题,您可以使用任何 RSpecs 其他关键字来形成新的范围,例如
feature "post message" do
context "with no user" do
scenario "unsuccessfully post a message no user" do
visit messages_path
fill_in "message[content]", with: "This is the content of my message."
click_button "Post a Message"
expect(page).to have_content "User must exist"
end
end
context "with a user" do
before(:each) do
visit new_user_path
fill_in "user[name]", with: "John"
click_button "Sign In"
visit messages_path
end
scenario "successfully post a message" do
fill_in "message[content]", with: "This is the content of my message."
click_button "Post a Message"
expect(page).to have_content "This is the content of my message"
expect(page).to have_current_path(messages_path)
end
scenario "unsuccessfully post a message no content" do
fill_in "message[content]", with: ""
click_button "Post a Message"
expect(page).to have_content "Content is too short"
end
scenario "messages page should have a log out button" do
click_button "logout"
expect(page).to have_current_path(new_user_path)
end
end
end
此外,您不应将 RSpecs 内置匹配器(eq
等)与 Capybara 一起使用 - 而是使用 Capybara 提供的匹配器,在本例中 have_current_path
如我所示多于。这些具有重试行为,并且在您处理包含异步行为的页面时会导致更稳定的测试。
我正在尝试熟悉 Capybara 和其他 TDD,但我失败了。我在这里的第一个例子(场景 "unsuccessfully post a message no user" do)应该是失败的,因为我没有输入用户,但无论如何它都会以某种方式输入,而不是收到预期的 "User must exist" 它说 "Welcome John" .我的 'before(:each)' 是否在它出现后仍会击中它,还是我有其他问题?
/spec/features/mess_spec.rb
require 'rails_helper'
feature "post message" do
scenario "unsuccessfully post a message no user" do
visit messages_path
fill_in "message[content]", with: "This is the content of my message."
click_button "Post a Message"
expect(page).to have_content "User must exist"
end
before(:each) do
visit new_user_path
fill_in "user[name]", with: "John"
click_button "Sign In"
visit messages_path
end
scenario "successfully post a message" do
fill_in "message[content]", with: "This is the content of my message."
click_button "Post a Message"
expect(page).to have_content "This is the content of my message"
expect(current_path).to eq(messages_path)
end
scenario "unsuccessfully post a message no content" do
fill_in "message[content]", with: ""
click_button "Post a Message"
expect(page).to have_content "Content is too short"
end
scenario "messages page should have a log out button" do
click_button "logout"
expect(current_path).to eq(new_user_path)
end
end
我的 spec/models/message_spec.rb 在第二次测试时遇到了类似的问题
it "should not save if no user" do
expect(build(:message)).to be_invalid
end
也没有失败,尽管我只是通过跳过工厂机器人来作弊所以这是我当前的工作文件
require 'rails_helper'
RSpec.describe Message, type: :model do
it "should save" do
expect(build(:message, user: build(:user))).to be_valid
end
it "should not save if no user" do
message = Message.new(
content: 'This is a message'
)
expect(message).to be_invalid
end
it "should not save content is too short" do
message = Message.new(
content: 'This',
user_id: '1'
)
expect(message).to be_invalid
end
end
您猜对了您的问题 - scenario
只是定义了测试 - 它没有定义测试的顺序,最佳做法实际上是 运行 您的测试以随机顺序确保您在各个测试之间没有任何耦合。这意味着在同一范围或更高范围内定义的任何 before(:each)
将在该范围内指定的每个 scenario
之前 运行。
要解决这个问题,您可以使用任何 RSpecs 其他关键字来形成新的范围,例如
feature "post message" do
context "with no user" do
scenario "unsuccessfully post a message no user" do
visit messages_path
fill_in "message[content]", with: "This is the content of my message."
click_button "Post a Message"
expect(page).to have_content "User must exist"
end
end
context "with a user" do
before(:each) do
visit new_user_path
fill_in "user[name]", with: "John"
click_button "Sign In"
visit messages_path
end
scenario "successfully post a message" do
fill_in "message[content]", with: "This is the content of my message."
click_button "Post a Message"
expect(page).to have_content "This is the content of my message"
expect(page).to have_current_path(messages_path)
end
scenario "unsuccessfully post a message no content" do
fill_in "message[content]", with: ""
click_button "Post a Message"
expect(page).to have_content "Content is too short"
end
scenario "messages page should have a log out button" do
click_button "logout"
expect(page).to have_current_path(new_user_path)
end
end
end
此外,您不应将 RSpecs 内置匹配器(eq
等)与 Capybara 一起使用 - 而是使用 Capybara 提供的匹配器,在本例中 have_current_path
如我所示多于。这些具有重试行为,并且在您处理包含异步行为的页面时会导致更稳定的测试。