Ruby 如何测试具有依赖性的主题?

Ruby 如何测试具有依赖性的主题?,ruby,unit-testing,rspec,mocking,tdd,Ruby,Unit Testing,Rspec,Mocking,Tdd,我想用Ruby开发一个基于卡的游戏,我想用TDD的方式来做 我想写的第一个类是Player。 每位玩家有一手牌,共13张,轮到他/她时可以选择并使用1张牌进行传球 我没有开发任何其他类(如卡片、手等),我想知道如何测试这个依赖于其他类的主题 我知道mock,但我不知道如何使用它们 例如,在这个场景中,我们知道当一个玩家玩一张牌时,该牌应该从他/她的手上移除 这是我的代码: require "rspec" require "lib/player" describe Player do bef

我想用Ruby开发一个基于卡的游戏,我想用TDD的方式来做

我想写的第一个类是Player。 每位玩家有一手牌,共13张,轮到他/她时可以选择并使用1张牌进行传球

我没有开发任何其他类(如卡片、手等),我想知道如何测试这个依赖于其他类的主题

我知道mock,但我不知道如何使用它们

例如,在这个场景中,我们知道当一个玩家玩一张牌时,该牌应该从他/她的手上移除

这是我的代码:

require "rspec"
require "lib/player"

describe Player do
  before(:each) do
    hand=mock("Hand")
    hand.should_receive(:count).and_return(13)
    subject.hand=hand
  end

  it "should choose and play a card from her/his hand" do
      subject.hand.count.should==13
      card_selected=subject.play(2)      # card #2 in his/her hand
      subject.hand.count.should=12
   end
end

此外,在实现中,我们依赖于Hand类,我如何处理它?

我看到了我的模拟和存根,我看到了巨大的测试套件通过了,尽管应用程序被破坏得难以置信,因为一半的代码已经不存在了

我得出的结论是,在使用存根和嘲弄时应该格外小心。事实上,它应该尽可能晚地推出

这是其中一种嘲笑为时过早的情况。你嘲笑的原因仅仅是因为你还没有掌握
这门课

作为旁注,测试本身需要改进。仔细看一下这些行:

hand.should_receive(:count).and_return(13)
subject.hand=hand
subject.hand.count.should==13
subject.hand.count.should=12
当然,
subject.hand.count.should==13
传递,您只需将其存根到这个值即可。当然,
subject.hand.count.should=12通过,因为您没有调用
=
。如果你把它变成一个真正的期望,你会想为什么它会失败。它失败了,因为您将
Hand#count
短截图为始终返回13

实际上,您在这里所做的是模拟正在测试的API的一部分。不要这样做。相反,从婴儿步开始。这可能意味着:

  • 你从内部开始,努力走出去。因此,从最里面的类开始,在本例中为
    Hand
    。一旦你到达
    Player
    ,所有的部件都会很好地装配在一起,而不会受到嘲弄

  • 您从
    Player
    开始,直到您完全需要另一个类为止(如果“有意义的API”的参数吸引您,请这样做)。这意味着:等待
    Hand
    上出现
    namererror
    。然后根据需要实现尽可能多的
    Hand
    类。然后回到
    Player


此外,查看您的代码会提出一个问题:出于好奇,您为什么要首先将玩家和她的手分开?

也许您已经超越了自己。你不应该仅仅因为手还不存在就模仿它。这将导致您在创建Hand类后重写测试。考试不应该改变。推迟测试play方法,直到你有一个基本的手类来测试它。我不同意。在拥有支持类之前编写测试将帮助您编写更有意义的API,因为您基本上是在为希望拥有的API编写测试。然后你去实现API使测试通过。我认为Marc Talbot是对的,Mock的一个用法是在不知道其依赖性的情况下测试subject。添加Hand类后,你会离开Mock吗?如果更改count方法的行为会发生什么?然后你有一些测试应该失败但通过了,因为你没有达到实际的类方法。汤姆,我不知道,这就是我问的原因。我已经按照您建议的方式开发了代码,但仍然渴望学习最佳方法