在 Rails 单元测试中使用 assert_match 和正则表达式

Using assert_match with regex in Rails unit tests

我正在研究 Rails 教程第 11 章前 2

教程要求通过替换FILL_IN变量来完成测试以检查微博数量(可以是任意数量)

  test "micropost sidebar count" do
    log_in_as(@user)
    get root_path
    assert_match "#{FILL_IN} microposts", response.body
    # User with zero microposts
    other_user = users(:mallory)
    log_in_as(other_user)
    get root_path
    assert_match "0 microposts", response.body
    other_user.microposts.create!(content: "A micropost")
    get root_path
    assert_match FILL_IN, response.body
  end

在第一个 FILL_IN 中,我为任何数字添加了一个正则表达式 /^[1-9]\d*$/ 并尝试通过将其分配给如下变量来对其进行插值

regex_number = /^[1-9]\d*$/
assert_match "#{regex_number } microposts", response.body

这对我不起作用(我的灯具的响应正文中有 34 个微博)

我使用工具检查了正则表达式,应该有匹配项 34

最后一件事,你如何检查微博等复数的匹配 这是因为最后的FILL_IN是给“1条微博”的

有趣的是,您选择尝试使用 REGEX 来解决这个问题。虽然我没有这些示例的答案,但我开始以不同的方式解决第一个 FILL_IN - 利用同一章前面的 integration/user_profile_test.rb 文件中的知识。您是否出于任何特定原因选择了 REGEX 路线?

至于第二个FILL_IN,我想你可能想多了——答案可以从你上面转录的Hartl提供的"micropost sidebar count"代码中推断出来。 ;-)

您不应在此练习中使用正则表达式。但是让我们一步一步来:

首先,我认为正则表达式不能用引号引起来。插值后,您的代码显示为 assert_match "/^[1-9]\d*$/ microposts", response.body。对于 assert_match,您想要匹配正则表达式或字符串,而不是两者。您应该删除插值,删除引号,然后将 'microposts' 放在正则表达式中。

其次,我认为您的正则表达式不适合这种情况。 '^' 匹配字符串的开头,'$' 匹配字符串的结尾,但是 assert_match 将您的正则表达式与一个字符串进行比较:主页的整个正文!你真的不在乎匹配在哪里,只要它存在于字符串中的某个地方即可。这使得开始和结束锚点不适合该搜索。

这是通过此测试的正则表达式版本:

assert_match(/[1-9]\d microposts/, response.body)

但这对于此测试旨在完成的内容来说太笼统了。您不想在页面上只查找任何数字。您要查找正确 条微博显示在 'microposts'.

字之前

环顾网络,这是大多数人完成此练习的 FILL_INs 的方式:

assert_match "#{@user.microposts.count} microposts", response.body

assert_match "#{other_user.microposts.count} micropost", response.body

有些人甚至只是简单地填写了他们希望测试找到的数字,而不是查看用户对象中的数字,但我认为这太容易破解了,而且可能不是 Hartl 的意图。


至于Pluralize...我为这个问题苦思了很久。经过千辛万苦,我终于找到了两种方法。老实说,我不认为 Hartl 打算让我们在这次测试中使用它,因为他以前从未在测试中使用过它。我认为他想让我们直接在搜索字符串中输入正确的复数形式,如上所示。

无论如何,如果你真的想这样做,这里有两种方法可以用复数形式完成第二个FILL_IN:

assert_match "#{other_user.microposts.count} micropost".pluralize(other_user.microposts.count), response.body

assert_match ActionController::Base.helpers.pluralize(other_user.microposts.count, "micropost"), response.body

在实践中,您可能希望通过执行以下操作来提高可读性:

num = other_user.microposts.count
assert_match "#{num} micropost".pluralize(num), response.body