这个Rspec语法究竟要求什么?

时间:2017-12-05 22:14:57

标签: ruby rspec rspec-rails

TL; DR明年我要去训练营,他们的评估是学习红宝石。我有JS的背景,对ruby来说很新。我有这个评估,在这种情况下,我不熟悉测试要我做什么。下面是测试用例(Rspec),就在下面,这是我的答案。

describe "some silly block functions" do
  describe "reverser" do
    it "reverses the string returned by the default block" do
      result = reverser do
        "hello"
      end

  expect(result).to eq("olleh")
end

it "reverses each word in the string returned by the default block" do
  result = reverser do
    "hello dolly"
  end

  expect(result).to eq("olleh yllod")
  end
end

这是我的答案代码:

def reverser sentence
  words = sentence.split(" ")
  result = []

  words.length.times do |i|
    result.push(yield(words[i]))
  end

  result.join(" ")
end

reverser("hello dolly") {|n| n.reverse} #=> 'olleh yllod'

正如我上面提到的,我是ruby的新手,屈服的想法就像JS的回调函数。我很难弄清楚测试用例要求我编写的预期代码。它表示'它会反转默认块返回的字符串中的每个单词'我刚刚在函数外部创建了一个块,而这个块正在被反转。我感谢任何可以提供建议的人的帮助和指导。

3 个答案:

答案 0 :(得分:4)

这更多是关于TDD而不是Ruby。这种方法在任何其他语言中都是一样的。

TDD的目的是编写可能失败的最简单的测试,然后编写可能更改错误消息的最简单的代码。在这个例子中已经提供了步骤#1,所以这实际上是关于第2步:编写可能改变消息的最简单的代码。

让我们进行测试吧!消息说:

 NoMethodError:
   undefined method `reverser' …

哪些最简单的代码可能会更改一条消息,说明方法不存在?好吧,当然,让方法存在!

def reverser; end

现在,消息是:

expected: "olleh"
     got: nil

好的,所以我们希望我们返回字符串'olleh',但实际上我们返回了nil。这很简单:

def reverser; 'olleh' end

大!第一次测试通过。但第二个仍然失败。它说:

expected: "olleh yllod"
     got: "olleh"
嗯......显然,仅仅静态回归是不够的。我们每次都必须返回不同的东西。明显的来源是一个参数,但我们的方法没有任何参数。或者是吗?是!在Ruby中,所有方法都有一个隐式的块参数!您可以使用yield关键字对其进行评估,因此请尝试:

def reverser; yield end

该死!我们回到了两个错误!那是倒退了一步。或者是吗?让我们看看第一条错误消息:

expected: "olleh"
     got: "hello"
你注意到了什么吗?预期值与我们当前返回的值完全相反。所以,我们需要做的就是反转返回值:

def reverser; yield.reverse end

万岁!我们回到了1个错误:

expected: "olleh yllod"
     got: "yllod olleh"

再一次,你能发现发生了什么吗?单词的顺序颠倒了!我们需要将这些词分开,然后将它们反转,然后将它们重新组合在一起:

def reverser; yield.reverse.split.reverse.join end

如此接近!

expected: "olleh yllod"
     got: "ollehyllod"

我们只需要把空间放回去:

def reverser; yield.reverse.split.reverse.join(' ') end

Yippieh!

2 examples, 0 failures

重要的是:我们实际上不得不思考。每一步,测试告诉我们该做什么,接下来要做什么,以及什么时候完成。这就是TDD的意义:测试驱动开发。

答案 1 :(得分:0)

yield表示"执行块内的代码并给出结果"。您的reverser方法可以简单地写成:

def reverser
  yield.split.map(&:reverse).join(' ') if block_given?
end

result = reverser do
  'hello world'
end

puts result
# => olleh dlrow

Ruby会自动返回最后一个被称为返回值的东西,因此赋予reverser的块的返回值为hello world,这将分配给yield

您可以查看block_given? here的文档。请查看this answer以获得更深入的块解释

答案 2 :(得分:0)

我认为问题的关键应该是解释RSpec和TDD,如果你正在进行训练营。我认为给你解决问题的答案只是你在这种情况下需要知道的部分内容。所以...

TDD的一个原则是编写最少量的代码以使测试通过。如果我回到起点。

您编写了sentence方法,将def reverser sentence 'olleh' end 作为参数:

wrong number of arguments

运行测试,测试失败并显示错误:def reverser 'olleh' end 。删除参数并尝试再次运行RSpec:

olleh

第一个测试应该通过,但是第二个测试将失败,因为我们已经对yield的返回值进行了硬编码。显然,返回硬编码值并不好 - 它只是帮助测试通过 - 所以我需要弄清楚如何def reverser yield.reverse end 返回值。

{{1}}

这也许会让第二次测试通过......

这是TDD的指导原则,采取小步骤并让您的代码通过。一旦它通过,然后返回并重构并改进您的代码。

正如您可能已经知道TDD对于编写高质量代码非常宝贵 - 它使编写代码变得有趣,它有助于重构。

我找到了一个包含resources的页面,我建议使用codeschool但是他们已经退出了他们的课程,这很可惜但是有一个PluralSight TDD course可能有用而且还有一个{{ 3}}这也可能对你有所帮助。