【问题标题】:Michael Hartl Rails tutorial: assert_not does exact opposite of what it should and I don't understand whyMichael Hartl Rails 教程:assert_not 与它应该做的完全相反,我不明白为什么
【发布时间】:2015-09-03 04:47:29
【问题描述】:

tl;dr 有效名称不会因为测试失败而被写入数据库,而无效名称会因为测试通过而被写入数据库。

编辑: 为了澄清项目和我的一般问题:如书中所述,此用户模型设置为开始阶段,以允许网站用户最终登录进入一个网站。数据库列将是“名称”和“电子邮件”,每一行将是一个用户(假设用户名和电子邮件是有效的)。为了进一步说明,我在下面编辑了我的原始帖子,所有编辑都以斜体显示。

此外,请仅在您可以在我的帖子中按原样解释代码的情况下回复 - 不建议添加额外的代码以使其工作。我正在使用的教科书断言该代码应该按原样工作,但它的评估结果似乎与它应该的相反。最后,如果您知道其他更详细地解释这一点的链接,那将很有帮助;但是,我已经阅读了apidockRoR API 以及 Google 搜索中显示的大多数 SO 链接,但没有一个有助于解释这个问题。

我正在学习 Michael Hartl 的 Ruby on Rails 教程。我在第 6 章进行验证测试,但我一直在验证是否存在名称。尽管我完全按照教程进行了操作,但它似乎与教程所说的应该做的完全相反(即验证一个无效的名称条目)。我还在网上搜索了有关assert_not 工作原理的更多详细信息,但找不到任何有用的详细信息。这是我经历的过程。

  1. 添加一个我们知道会失败的测试:

    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,它将真值转换为假,并使测试失败。

  1. 我们添加一个验证测试:

    class User < ActiveRecord::Base
      validates :name, presence: true
    end
    

这为 User 模型设置了一个验证规则,以确保 :name 对象具有内容并且不是 nil、空字符串或空格。到目前为止还是不错的。

  1. 这就是事情变得棘手的地方。此时,我们测试中的表达式@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 的无效值,因此允许将包含空格的名称写入数据库,而这与我们试图实现的完全相反,即,防止空白名称写入数据库。

  1. 相反,我用一个有效的名称计算出这个逻辑:

    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


【解决方案1】:

测试通过了无效值 :name,因此允许写入由空格组成的名称 到数据库...

assert_not 如果后面的表达式 @user.valid? 返回 false,则返回 true(与测试通过相同)。实际上,第 3 节中的测试说:我们没有断言用户是有效的。由于该期望/断言是正确的,因此它返回 true 并且测试通过。没有任何内容保存到数据库中。

【讨论】:

  • 完全正确.. 只是为了澄清,它是说“我们断言'用户是有效的'(表达式)是不真实的”。因此,它不会保存在数据库中。如果user.valid? 为空白,则断言返回true,这意味着用户无效。见这里:apidock.com/rails/ActiveSupport/Testing/Assertions/assert_not
  • 我已经更新了我的原始帖子,对原始问题进行了更多说明。这些反应几乎是有道理的,但并不完全。 “我们没有断言用户是有效的”(至少在这种情况下)与“我们断言用户无效”的含义相同,但是测试通过了,它将这个无效用户写入数据库.正如我在原始帖子中解释(并澄清)的那样,有效用户条目的情况正好相反:测试失败,因此用户没有写入数据库。
  • assert 或 assert_not 语句不允许/禁止写入测试/生产数据库。所有这些语句所做的只是返回真或假(通过或失败)。您是否有理由相信正在保存无效的用户记录?
【解决方案2】:

您可以添加一个验证,因为您添加了一个由两个空格组成的字符串“”

  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: "example@example.com"
    assert_not @user.valid? 
    # => assert_not true 
end

【讨论】:

  • "presence: true" 已经不允许空字符串。 "allow_blank: false" 是不必要的。
【解决方案3】:

我遇到了同样的问题。只有presence: true 测试失败,当我添加allow_blank: false 时它通过了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-20
    相关资源
    最近更新 更多