2

我正在尝试编写一个测试来防止你做同样的事情两次(在这种情况下,在 tictactoe 中在同一个方格上玩两次),但是 RSpec 语法让我感到困惑,我在他们的文档中看不到解决方案。我尝试了一些没有成功的方法,这让我意识到我并不像我想象的那样理解 RSpec 语法。

因为测试是针对递归方法的,所以很多错误不像我想要的那样具有描述性,因为它们会导致程序崩溃,这使得很难隔离问题。

我尝试测试/创建的方法最初看起来像这样:

def your_turn

your_turn unless play_on(square_at(get_row, get_square))

结尾

(如果没有成功放置标记,play_on 返回 nil)

在这种情况下,我正在测试一个模块,your_turn、get_row 和 get_square 是该模块的方法,但 play_on 和 square_at 是它要集成到的类中的方法,所以我在必要时进行存根(同上 get 方法,因为我不想得到 RSpec 的提示)。

我尝试的第一个测试是这样的:

“如果玩家不能在那个方格上玩,它会重复这个过程”做

allow(human).to receive(:play_on).and_return(nil, :square)

expect(human).to receive(:your_turn).twice

human.your_turn

结尾

测试失败,并说它只收到过一次。我期望这种展开的方式是在最初的 your_turn 调用中,RSpec 将存根 play_on,返回 nil,设置 unless 语句并重复 your_turn 调用 - 之后它将返回一个符号并防止任何进一步的递归。我误解了什么?

经过那次努力,我想出了一个似乎有效的怪物,但我不完全确定为什么:

allow(human).to receive(:get_row).and_return(1,2)

allow(human).to receive(:get_square).and_return(2,2)

allow(human).to receive(:square_at).with(1, 2).and_return(:nil)

allow(human).to receive(:square_at).with(2, 2).and_return(:square)

allow(human).to receive(:play_on).with(:square).and_return(:square)

期望(人类)。接收(:play_on)。两次

human.your_turn

这里的麻烦(除了丑陋之外)是我让它通过蛮力而不是理解来工作,而且有几件事我不确定:

  • 为什么我不能在没有提示返回 RSpec 的情况下删除例如前两行?由于在第三行和第四行我将调用 get_ 方法的方法 square_at 存根,为什么它们仍然被调用?
  • 同样,第五行第三和第四行似乎涵盖了第三和第四行,但我最初有最后一个“允许”返回(nil,:square),希望它能起作用。最终调用 your_turn 三次,而我期望两次,所以我删除了 nil 并且它通过了。我解析它的方式,没有 nil,play_on 将立即返回 :square,因此不会触发除非逻辑并且该方法将终止。再说一遍,我误解了什么?
  • 是否有处理两条“square_at”允许行的更简单的方法?

谢谢大家,

萨沙

4

1 回答 1

0

我不明白你的问题(特别是第二个和第三个),但我相信你的问题的很大一部分是认为仅仅因为你存根了一个方法调用,Ruby 不会评估方法调用参数。

get_rowget_square方法在之前被调用square_at。Ruby 从“右到左”“解析”语句,因此它首先调用get_row,然后get_square最后square_at传递两个 get_ 方法的结果。根据这两种方法的作用,这可能会破坏您的测试,并解释了为什么需要前两个存根。

于 2014-08-28T16:31:02.217 回答