【发布时间】:2015-09-03 04:47:29
【问题描述】:
tl;dr 有效名称不会因为测试失败而被写入数据库,而无效名称会因为测试通过而被写入数据库。
编辑: 为了澄清项目和我的一般问题:如书中所述,此用户模型设置为开始阶段,以允许网站用户最终登录进入一个网站。数据库列将是“名称”和“电子邮件”,每一行将是一个用户(假设用户名和电子邮件是有效的)。为了进一步说明,我在下面编辑了我的原始帖子,所有编辑都以斜体显示。
此外,请仅在您可以在我的帖子中按原样解释代码的情况下回复 - 不建议添加额外的代码以使其工作。我正在使用的教科书断言该代码应该按原样工作,但它的评估结果似乎与它应该的相反。最后,如果您知道其他更详细地解释这一点的链接,那将很有帮助;但是,我已经阅读了apidock、RoR API 以及 Google 搜索中显示的大多数 SO 链接,但没有一个有助于解释这个问题。
我正在学习 Michael Hartl 的 Ruby on Rails 教程。我在第 6 章进行验证测试,但我一直在验证是否存在名称。尽管我完全按照教程进行了操作,但它似乎与教程所说的应该做的完全相反(即验证一个无效的名称条目)。我还在网上搜索了有关assert_not 工作原理的更多详细信息,但找不到任何有用的详细信息。这是我经历的过程。
-
添加一个我们知道会失败的测试:
require 'test_helper' class UserTest < ActiveSupport::TestCase def setup @user = User.new(name: "Example User", email: "user@example.com") 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? 评估为真,因为没有设置验证,所以测试认为一个全为空白的名称空格有效。这前面是assert_not,它将真值转换为假,并使测试失败。
-
我们添加一个验证测试:
class User < ActiveRecord::Base validates :name, presence: true end
这为 User 模型设置了一个验证规则,以确保 :name 对象具有内容并且不是 nil、空字符串或空格。到目前为止还是不错的。
-
这就是事情变得棘手的地方。此时,我们测试中的表达式
@user.valid?应该(并且确实)评估为false,因为验证规则不允许:name中只有空格。我在此代码旁边添加了 cmets,以帮助我了解在此过程中分配和评估了哪些值:test "name should be present" do @user.name = " " # => name: " " email: "example@example.com" 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。同样,“我们不断言用户是假的”,其评估结果为真。
这就是我的问题所在:测试传递了:name 的无效值,因此允许将包含空格的名称写入数据库,而这与我们试图实现的完全相反,即,防止空白名称写入数据库。
-
相反,我用一个有效的名称计算出这个逻辑:
test "name should be present" do # => name: "Example User" email: "example@example.com" assert_not @user.valid? # assert_not true => false end
在这种情况下,由于@user.valid? 的计算结果为真(因为“示例用户”是有效名称),assert_not @user.valid? 的计算结果为假,测试失败,我们的有效名称不会写入数据库。 在伪代码中,这一行可以这样翻译:assert_not (is the user valid? yes) ==> assert_not(true) ==> false。类似地,“我们不断言用户为真”,其评估结果为假。因为测试评估为假(即使使用真/有效的用户名),这个有效的名称不会写入数据库。
如果有人能解释这有什么意义,我将不胜感激,详细的答案会引导我完成它会更好。
【问题讨论】:
-
如果将
@user.name = " "更改为单个空格,测试是否通过?如果你把它改成@user.name = nil,它会通过吗? -
validates :name, presence: true, allow_blank: false试试这个
标签: ruby-on-rails ruby validation tdd assertions