1

我有这个方法作为一个更大的类的一部分。我正在尝试为它编写一个测试,但我是 rspec 的新手,我有点难过......如果我注释掉 9.times 循环中的所有内容,我可以测试“drawgrid”。但如果我取消注释该代码,当前测试将失败。我需要测试 play 方法...运行游戏。它放置'drawgrid'......运行游戏序列9次,每回合后放置'drawgrid'。但我不知道该怎么做。非常感谢任何指针。

以下是播放方法及其当前规格

      def play
        #draw the board
        puts drawgrid

        #make a move
        turn = 0

        9.times do

          if turn.even?

            @player = @player_h.move_human("X", @board)

            @move = @player.to_sym
            @marker = @player_h.boardpiece

            does_move_exist(@move,@marker)
            is_a_human_win(@board)

          else

            @player = @player_c.move_computer("O", @board)

            @move = @player
            @marker = @player_c.boardpiece

            does_move_exist(@move,@marker)
            is_a_computer_win(@board)

          end

          puts drawgrid

          turn += 1
        end # 9.times ends
      end

当前规格....

      describe 'play method' do
        it 'draws the game grid' do
          @player_human = Player.new('X')
          @player_computer = Player.new('O')
          @board = Board.new
          @game = Game.new(@player_human, @player_computer, @board)

          @game.should_receive(:puts).with("\na  | |  \n----------\nb  | |  \n----------\nc  | |  \n----------\n  1 2 3\n")

          @game.play
        end
      end
      describe '9.times' do
        it 'runs game sequence 9 times...once per board spot' do
          @player_human2 = Player.new('X')
          @player_computer2 = Player.new('O')
          @board2 = Board.new
          @game2 = Game.new(@player_human2, @player_computer2, @board2)

          turn = 0       
          9.times do
            if turn.even?
              @player_human2.should_receive(:puts).with("human move...")
              @player_human2.stub(:gets).and_return("b2")
            else
              @player_human2.should_receive(:puts).with("computer move...")
              @player_human2.stub(:gets).and_return("a1")
            end
            turn += 1
          end
        @game2.play
        end
      end
4

2 回答 2

3

我赞同戴夫所说的话。尝试简化。基本上,如果您可以简化您的播放方法,它将简化您的测试。现在游戏关注的是每一回合的实施细节。把这些细节往下推,你的测试会变得更容易编写和更细化。我不是最好的,我对此也不是很满意,但希望下面的代码能把你推向正确的方向:

#play.rb

class Board
end

class Player
  def initialize(symbol)
    @symbol = symbol
  end

  def take_turn
  end
end

class Game
  def initialize(player1, player2, board)
    @player1, @player2, @board = player1, player2, board
  end 

  def play
    drawgrid

    (0...9).each do |turn|
      turn.even? ? @player1.take_turn : @player2.take_turn
      drawgrid
    end
  end

  def drawgrid
  end
end

和测试文件:

#play_spec.rb
require './play.rb'

describe '#play' do
  before do
    @player1 = Player.new('X')
    @player2 = Player.new('O')
    @game = Game.new(@player1, @player2, Board.new)
  end

  it 'draws the game grid' do
    @game.should_receive(:drawgrid).at_least(:once)
    @game.play
  end

  it 'runs game sequence 9 times...once per board spot' do
    @player1.stub(take_turn: true)
    @player2.stub(take_turn: true)
    @player1.should_receive(:take_turn).exactly(5).times
    @player2.should_receive(:take_turn).exactly(4).times
    @game.play
  end
end
于 2012-10-19T19:12:21.233 回答
3

总的来说,我觉得您的代码和测试都试图在一种方法中做太多事情。关于您的播放方法的有趣之处与其说是循环中发生的 9 次。我对重构的第一个建议是将循环内的内容转换为名为“take_turn”或类似的方法。

然后,您可以为单回合发生的情况编写规范。而且,您对 play 方法的规范将测试 take_turn 方法是否被调用了 9 次。

这并不是说你不能保持你的代码保持原样并为它编写一个有效的测试......你只是不能对你正在测试的东西进行超级外科手术。

希望有帮助。

于 2012-10-18T21:07:43.433 回答