2

私はブラックジャックゲームに取り組んでいます。私のゲームオブジェクトには、デッキが一定の浸透レベルに達した後にシャッフルされるデッキオブジェクトが含まれています。私のメソッドの多くは、このデッキオブジェクトに依存しています。セッターメソッドを介してデッキオブジェクトにアクセスできる理由はわかりません。ゲームクラスのメソッドはランダムなデッキの順序に依存しているため、テストに問題があります。

たとえば、deal_handメソッドがあります。

def deal_hand(player)
    reset_deck if @deck.size < 2
    player.hands.push(Hand.new(*@deck.pop(2)))
end

このような方法をどのようにテストする必要がありますか?@deckインスタンス変数で使用されるDeckオブジェクトを手動で作成できると思っていました。残念ながら、インスタンス変数を設定することはできません。また、テスト以外に「設定可能」である理由がないため、セッターを追加したくありません。テストファイルからクラスにモンキーパッチを適用し、セッターを追加する必要がありますか?

余談ですが、私は主にスクリプトを作成しますが、このプロジェクトが手に負えなくなった後、テストの作成を開始する必要があると判断しました。「パターンのテスト」のための標準的なリソースはありますか?

編集:

スタブ/モックをサポートするMiniTestを使用しています。私の知る限りでは、モックオブジェクトのメソッド呼び出しに期待される戻り値を設定することしかできません。モックデッキを作成した場合、実際のデッキオブジェクトも内部配列に依存します。デッキを呼び出すコードはいずれも、配列に直接アクセスしません。

4

3 に答える 3

2

モックライブラリを使用します。RSpecには1つが組み込まれていますが、私はそれが嫌いなので、私が書いたSurrogateでどのように見えるかを示します。

class Deck
  def pop(n)  end
  def reset() end
  def size()  end
end

class Game
  def initialize(deck)
    @deck = deck
  end

  def deal_hand(player)
    reset_deck if @deck.size < 2
    player.hands.push(Hand.new(*@deck.pop(2)))
  end

  def reset_deck
    @deck.reset
  end
end

Hand = Struct.new :card1, :card2

class Player
  def hands
    @hands ||= []
  end
end

require 'surrogate/rspec'
class MockDeck
  Surrogate.endow self
  define(:reset)
  define(:pop)  { |n| n.times.to_a }
  define(:size) { 1 }
end

describe Game, 'deal_hand' do
  let(:deck)   { MockDeck.new }
  let(:player) { Player.new }
  let(:game)   { Game.new deck }

  it 'resets the deck if there are less than 2 cards' do
    deck.will_have_size 2 # set the return value of deck.size
    game.deal_hand player
    deck.was_not told_to :reset # assert what happened to the deck

    deck.will_have_size 1
    game.deal_hand player
    deck.was told_to :reset
  end

  it 'deals the top 2 cards to the player' do
    deck.will_pop [:card1, :card2]
    game.deal_hand player
    deck.was told_to(:pop).with(2)
    player.hands.last.should == Hand.new(:card1, :card2)
  end
end

describe Deck do
  it 'is substitutable for the mock' do
    # because we use the mock in tests
    # we want to make sure its interface matches the real deck
    Deck.should substitute_for MockDeck
  end
end
于 2013-03-24T08:12:50.920 に答える
1

モカの使用を検討しましたか?

これにより、デッキをスタブまたはモックして、テスト実行に期待されるカードが確実に含まれるようになります。

于 2013-03-24T07:42:04.970 に答える
1

テストでは、オブジェクトのrubyメソッドであるメソッドinstance_variable_setを使用します。

だから私はあなたのメソッドがGameクラスにあると仮定しているので、あなたが次のようなものを設定しているならあなたは

@test_deck = something_that_sets_up_state_of_test_deck

@game = Game.new
@game.instance_variable_set(:deck, @test_deck

これにより、attr_accessibleやgetterおよびsetterを明示的に構築しなくても、Game内でインスタンス変数が設定されます。

于 2013-03-24T07:54:37.407 に答える