我是Ruby编程的新手,但我认为我或多或少得到了一个符号(一个不可变的值,占用更少的空间,一个枚举等等)。这就是困扰我的 - 从一个Hartl Ruby on Rails教程中的Rake测试:
describe "something" do
let(:user) { FactoryGirl.create(:user) }
before { sign_in user }
...
end
调用FactoryGirl.create(:user)
对我来说是有意义的 - 在这里我们将一种标志(:user
)传递给FactoryGirl来告诉它要制作什么样的对象(或者更确切地说,是什么要设置的变量,因为它只创建User对象)。但是在let(user)
中,user
是一个变量,而不是一个符号(或至少它应该是)。我只能假设let
方法正在秘密地交换符号:user
以获取同名变量 - 但为什么呢? let(user)
不是一个更直观的语法吗?我在这里缺少什么?
此外,还有其他地方在Ruby中出现这种模式吗?到目前为止,我只在rake测试中看到它。
答案 0 :(得分:2)
就像Dave已经提到的那样,提供的代码不是rake任务,而是RSpec规范。
但是让我在这里关注真正的问题。
如果您从未接触过具有类似功能的任何其他语言,那么符号有点难以掌握。有些语言称之为Atom。
http://en.wikipedia.org/wiki/Symbol_(programming)
使符号变形的想法是提供一种人类可读但计算上便宜的原始类型。
在Ruby中,当编译器/解释器看到符号时,它会创建一个Symbol类型的对象并将其存储在内存中。在ruby中,符号是单例,因此任何其他对相同符号的使用都会返回完全相同的对象,这使得它在空间方面非常便宜并且比较便宜,因为您可以只比较内存地址而不是内容。 / p>
例如,如果比较两个符号,如下所示:
:foo == :foo
你几乎在比较同一个对象,这意味着只需要比较内存地址。
现在,当你比较两个字符串时:
"foo" == "foo"
它创建两个具有相同内容的String实例,并且需要比较字符串的每个字节以确保它们相等。
此属性使符号非常适合散列中的标识符或键。
现在,到RSpec。
我们来看下面的例子:
describe Authenticator do
let(:user) { Factory.create(:user) )
it "authenticate" do
auth_user = subject.authenticate(user.login, user.password)
auth_user.should == user
end
end
Factory.create将符号作为要使用的工厂的标识符。你需要自己定义工厂,所以它真的只是一个名字。你可以使用一个字符串,但使用符号更便宜和最好的做法,但老实说,除非你多次调用Factory.create百万次,否则它不会有太大的区别。
let不是定义一个变量,它实际上定义了一个做一些事情的方法:
这允许仅在需要时延迟创建对象,并允许将任何状态更改限制为当前规范。
因此,底线是:RSpec使用该符号作为方法名称的标识符,该名称将被生成以抽象掉某些事物,使您的生活更轻松。 RSpec只是一种BDD领域特定语言,它使用元编程来构建测试套件。
使用以下测试用例可以实现相同的行为:
class AuthenticatorTest < Test::Unit::TestCase
def user
return @user if @user
@user = Factory.create(:user)
end
def subject
return @subject if @subject
@subject = Authenticator.new
end
def teardown
@subject = nil
@user = nil
end
def test_authenticate
auth_user = subject.authenticate(user.login, user.password)
assert_equal auth_user, user
end
end
请注意,您可能不应该编写这样的测试用例,但它(粗略地)说明了RSpec的用途。
我希望有所帮助。
答案 1 :(得分:0)
一些小的更正/澄清:
我已经掩盖了let()内容的一些细节。真实的文档在这里:
https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/helper-methods/let-and-let
根据我个人的经验,这个特定的模式是nc,但是单元测试往往与常规代码不同,因为它们的想法是运用代码,而不是解决实际问题。要做到这一点,你往往希望一次改变一件事情,所以事情可能会重复 - 但ruby提供了许多工具来减少打字并保持可读性。
编辑:有关使用此模式的示例,请参阅注释。它在我的鼻子下......:)