tl; dr因为测试失败,所以未将有效名称写入数据库,而由于测试通过,因此无效名称也已写入数据库。
编辑: 为了澄清项目和我的一般问题:如书中所述,此用户模型被设置为开始阶段,以允许网站用户最终登录到网站。数据库列将是“名称”和“电子邮件”,并且每一行将是一个用户(假设用户名和电子邮件有效)。为了进一步澄清,我已经编辑了我的原始帖子,所有编辑均以斜体显示。
此外,仅当您可以在我的帖子中解释代码原样时,请回复-不要建议添加其他代码以使其正常工作。我正在使用的教科书断言该代码应按原样工作,但似乎却得出相反的结论。最后,如果您知道其他链接可以更详细地说明这一点,则很有帮助;但是,我已经阅读了apidock,RoR API和大多数出现在Google搜索中的SO链接,并且都没有帮助您阐明此问题。
我正在研究Michael Hartl的Ruby on Rails教程。我将在第6章中进行验证测试,并且坚持使用验证来确定名称的存在。即使我严格按照本教程进行操作,这似乎与本教程应做的操作正好相反(即验证无效的名称条目)。我还在网上和SO上搜索了有关assert_not
工作原理的更多详细信息,但找不到任何有用的详细信息。这是我经历的过程。
添加我们知道会失败的测试:
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
@user = User.new(name: "Example User", email: "[email protected]")
end
# resolves to true and passes
test "should be valid" do
assert @user.valid?
end
test "name should be present" do
@user.name = " "
assert_not @user.valid?
end
end
到目前为止很好。我很好地理解了这段代码,尽管第二个测试的措词很尴尬,但我认为assert_not @user.valid?
的工作方式如下:@user.valid?
计算为true,因为未设置任何验证,因此该测试认为名称全为空白空格有效。这之前是一个assert_not
,它将真实值转换为false,并使测试失败。
我们添加了一个验证测试:
class User < ActiveRecord::Base
validates :name, presence: true
end
这将为用户模型设置一个验证规则,以确保:name
对象具有内容且不为nil,空字符串或空格。到目前为止还不错。
这是棘手的地方。在这一点上,我们的测试中的表达式@user.valid?
应该(并且确实)求值为false,因为验证规则不允许其中仅包含空格的:name
。我在此代码旁边添加了注释,以帮助我了解在此过程中分配和评估的值:
test "name should be present" do
@user.name = " "
# => name: " " email: "[email protected]"
assert_not @user.valid?
# => assert_not false => true
end
@user.valid?
的计算结果为false,这使整个assert_not
表达式的计算结果为true,因此测试通过。 在伪代码中,此行可以这样翻译:assert_not (is the user valid? no)
==>assert_not(false)
==> true
。同样,“我们不断言用户为假”,其结果为true。
这是我的问题所在:测试传递了:name
的无效值,因此允许将由空格组成的名称写入数据库,而这与我们要实现的目的恰好相反,即,preventing空白名称不会写入数据库。
相反,我用有效名称得出了这个逻辑:
test "name should be present" do
# => name: "Example User" email: "[email protected]"
assert_not @user.valid?
# assert_not true => false
end
在这种情况下,由于@user.valid?
的值为true(因为“ Example User”是有效名称),所以assert_not @user.valid?
的值为false,测试失败,并且我们的有效名称未写入数据库。 在伪代码中,此行可以这样翻译:assert_not (is the user valid? yes)
==>assert_not(true)
==> false
。同样,“我们不会断言用户为真”,其结果为false。因为测试的结果为false(即使使用正确的用户名也是如此),所以不会将此有效名称写入数据库。
[如果有人可以解释这有什么意义,我将不胜感激,详细的答案会更好地指导我。
如果后面的表达式assert_not返回false,则测试通过了一个无效的值:name,因此允许写入由空格组成的名称到数据库...
@user.valid?
返回true(与测试通过相同)。实际上,第3节中的测试说:我们并不是在断言该用户有效。由于该期望/断言是正确的,因此它返回true,并且测试通过。什么都没有保存到数据库。
您可以在添加字符串“”时包含两个空格的同时添加验证
class User < ActiveRecord::Base
validates :name, presence: true, allow_blank: false
validate :name_of_valid
def name_of_valid
self.errors.add :base, 'My string can not be empty' if self.name == " "
end
end
然后
test "name should be present" do
@user.name = " "
# => name: " " email: "[email protected]"
assert_not @user.valid?
# => assert_not true
end
我有同样的问题。仅在使用presence: true
时测试失败,并且当我添加allow_blank: false
时测试通过。