ruby-on-rails – Rails教程:RSpec测试解耦
|
我想在Michael Hartl的
Ruby on Rails Tutorial中做
Exercise 2 of Chapter 8.5.练习如下:
按照第8.3.3节中的示例,浏览用户和身份验证请求规范(即当前在spec / requests目录中的文件)并在spec / support / utilities.rb中定义实用程序函数,以将测试与实现分离.额外功劳:将支持代码组织到单独的文件和模块中,并通过在规范帮助文件中正确包含模块来使一切工作正常. 例8.3.3:utilities.rb include ApplicationHelper
def valid_signin(user)
fill_in "Email",with: user.email
fill_in "Password",with: user.password
click_button "Sign in"
end
RSpec::Matchers.define :have_error_message do |message|
match do |page|
page.should have_selector('div.alert.alert-error',text: message)
end
end
定义的valid_signin(用户)函数在authentication_pages_spec.rb的以下块中使用,并且工作正常. describe "with valid information" do
let(:user){FactoryGirl.create(:user)}
before { valid_signin(user) }
it { should have_selector('title',text: user.name) }
it { should have_link('Profile',href: user_path(user)) }
it { should have_link('Sign out',href: signout_path) }
it { should_not have_link('Sign in',href: signin_path) }
describe "followed by signout" do
before { click_link "Sign out" }
it { should have_link('Sign in') }
end
end
所以在这个例子中,我开始创建自己的名为valid_signup(user): def valid_signup(user)
fill_in "Name",with: user.name
fill_in "Email",with: user.email
fill_in "Password",with: user.password
fill_in "Confirmation",with: user.password_confirmation
end
我在user_pages_spec.rb中使用这个块,如下所示: describe "with valid information" do
let(:user){FactoryGirl.create(:user)}
before { valid_signup(user) }
it "should create a user" do
expect { click_button submit }.to change(User,:count).by(1)
end
describe "after saving the user" do
before { click_button submit }
let(:user) { User.find_by_email(user.email) }
it { should have_selector('title',text: user.name) }
it { should have_selector('div.alert.alert-success',text: 'Welcome') }
it { should have_link('Sign out') }
end
end
它不起作用. Spork / Guard报告了这些错误: Failures:
1) UserPages signup with valid information should create a user
Failure/Error: expect { click_button submit }.to change(User,:count).by(1)
count should have been changed by 1,but was changed by 0
# ./spec/requests/user_pages_spec.rb:46:in `block (4 levels) in '
2) UserPages signup with valid information after saving the user
Failure/Error: before { valid_signup(user) }
NoMethodError:
undefined method `name' for nil:NilClass
# ./spec/support/utilities.rb:10:in `valid_signup'
# ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '
3) UserPages signup with valid information after saving the user
Failure/Error: before { valid_signup(user) }
NoMethodError:
undefined method `name' for nil:NilClass
# ./spec/support/utilities.rb:10:in `valid_signup'
# ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '
4) UserPages signup with valid information after saving the user
Failure/Error: before { valid_signup(user) }
NoMethodError:
undefined method `name' for nil:NilClass
# ./spec/support/utilities.rb:10:in `valid_signup'
# ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '
这些错误似乎表明在utilities.rb中的valid_signup(user)函数中的user.name没有定义,但我没有看到任何原因.我已经多次重启Guard了,并做了一个rake db:test:准备确保测试db(使用postgresql)是有序的. 这是我的factory.rb的完整性: FactoryGirl.define do
factory :user do
name "Example User"
email "user@example.com"
password "foobar"
password_confirmation "foobar"
end
end
在我继续尝试解耦更多的测试套件之前,我非常希望解决这个错误,更重要的是,了解它的原因. 编辑 我已经尝试了你的提示,并在user_pages_spec.rb中编辑了该函数,如下所示: describe "with valid information" do
before { valid_signup(user) }
it "should create a user" do
expect { click_button submit }.to change(User,:count).by(1)
end
describe "after saving the user" do
before { click_button submit }
let(:user) { User.find_by_email('user@example.com') }
it { should have_selector('title',text: user.name) }
it { should have_selector('div.alert.alert-success',text: 'Welcome') }
it { should have_link('Sign out') }
end
end
由于我从函数中删除了let(:user){FactoryGirl.create(:user)},因此我不再在函数中创建用户,所以我需要定义valid_signup(user),因为valid_signup的用户变量是不再被FactoryGirl填充: def valid_signup(user)
fill_in "Name",with: "Example User"
fill_in "Email",with: "user@example.com"
fill_in "Password",with: "foobar"
fill_in "Confirmation",with: "foobar"
end
这不起作用,并给了我以下错误: Failures: 我也尝试使用valid_signup(用户)以前的方式运行测试(使用user.name,user.email,user.password,user.password_confirmation,这也没有用,但有错误: Failures:
1) UserPages signup with valid information should create a user
Failure/Error: before { valid_signup(user) }
NameError:
undefined local variable or method `user' for #
# ./spec/requests/user_pages_spec.rb:42:in `block (4 levels) in '
2) UserPages signup with valid information after saving the user
Failure/Error: it { should have_selector('title',text: user.name) }
NoMethodError:
undefined method `name' for nil:NilClass
# ./spec/requests/user_pages_spec.rb:52:in `block (5 levels) in '
接下来我尝试运行它而不在user_pages_spec.rb中传递变量:在{valid_signup()}之前并且在utilities.rb中的函数中没有变量: def valid_signup()
fill_in "Name",with: "foobar"
end
这返回: Failures:
1) UserPages signup with valid information should create a user
Failure/Error: before { valid_signup(user) }
NameError:
undefined local variable or method `user' for #
# ./spec/requests/user_pages_spec.rb:42:in `block (4 levels) in '
2) UserPages signup with valid information after saving the user
Failure/Error: it { should have_selector('title',text: user.name) }
NoMethodError:
undefined method `name' for nil:NilClass
# ./spec/requests/user_pages_spec.rb:52:in `block (5 levels) in '
仍然没有更接近答案.我可能会忽略一些简单的事情.不知道是什么.我得到了我第一次做错的事情:我只是认为FactoryGirl是一种创建变量的方法,我不知道它实际上对我的测试数据库做了些什么. 解决方法
我将尝试解释原始测试中发生了什么(我发现比编辑版本更容易修复):
describe "with valid information" do
let(:user) {FactoryGirl.build(:user)} # FactoryGirl.create will save the instance,you should be using build instead
before { valid_signup(user) }
it "should create a user" do
expect { click_button submit }.to change(User,:count).by(1)
end
describe "after saving the user" do
before { click_button submit }
# let(:user) { User.find_by_email(user.email) } # this is not needed any more
it { should have_selector('title',text: 'Welcome') }
it { should have_link('Sign out') }
end
end
有关FactoryGirl用法的更多信息:https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#using-factories (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
