2013-05-02 53 views
-1

我正在写一个保龄球分数计算器,我试图设置RSpec测试,但由于某些原因,我无法让我的测试正常工作。Rspec实例变量和控制器测试

players_controller_spec.rb:

require 'spec_helper' 

describe PlayersController do 
    let(:player_names) { ["player1", 
         "player2", 
         "player3", 
        "player4"] } 

    describe "POST bowl" do 
    before(:each) do 
     @game = Game.create! 
     player_names.each do |name| 
     Player.create!(:name => name) 
     end 
     @game.players = Player.all 
     Player.all.each do |player| 
     (0..9).each do |number| 
      player.frames << Frame.create(:number => number) 
     end 
     end 
    end 
    describe "for the player's third bowl" do 
     before(:each) do 
     @game.players[@game.current_player].frames[9].update_attributes({:number => 9, :first_bowl => "X", :second_bowl => "X", :score => 20}) 
     @game.update_attributes({:current_player => 0, :current_frame => 9}) 
     end 

     describe "if the bowl is a number score" do 
     before(:each) do 
      post :bowl, {:score => "5", :id => @game.id} 
     end 

     it "should update the player's score" do 
      @game.players[@game.current_player].frames[@game.current_frame].score.should == 25 
     end 
     end 
    end 
    end 
end 

players_controller.rb

def bowl 
    @game = Game.find(params[:id]) 
    @score = params[:score] 

    @current_player = @game.current_player 
    @current_frame = @game.current_frame 
    @player = @game.players[@current_player] 

    @frame = @player.frames[@current_frame] 

    if @frame.first_bowl.nil? 
     @frame.first_bowl = @score 
     if @score == "/" 
     raise "Error" 
     end 
     if @score == "X" && @frame.number == 9 
     @frame.bonus = 2 
     end 
     @frame.score = (/\A[0-9]\z/ === @score ? @score.to_i : 10) 
    elsif @frame.second_bowl.nil? 
     @frame.second_bowl = @score 
     if @frame.score + @score.to_i > 10 
     raise "Error" 
     end 
     if @score == "X" 
     if @frame.number != 9 || (@frame.number == 9 && @frame.first_bowl != "X") # can't be a spare has to be number or strike 
      raise "Error" 
     end 
     end 
     if @score == "/" && @frame.number == 9 
     @frame.bonus = 1 
     end 
     if /\A[0-9]\z/ === @score 
     @frame.score += @score.to_i 
     elsif @score == "/" 
     @frame.score = 10 
     elsif @score == "X" 
     @frame.score = 20 
     end 
    elsif @frame.third_bowl.nil? 
     @frame.third_bowl = @score 
     if @frame.number != 9 
     raise "Error" 
     end 
     @frame.bonus = nil 
     @frame.update_attributes({:score => (/\A[0-9]\z/ === @score ? @frame.score + @score.to_i : @frame.score + 10)}) 
    else 
     raise "Error" 
    end 
    @frame.save 

    if @game.current_frame > 0 
     @prev_frame = @player.frames[@frame.number-1] 

     if @prev_frame.nil? 
     @prev_frame = Frame.create(:number => @game.current_frame-1) 
     @player.frames << @prev_frame 
     @player.frames = @player.frames.sort_by { |f| f.number } 
     end 

     update_scores 
    end 

有问题的规范是players_controller_spec.rb,并在试验开始我创建4名玩家全新的游戏和每个玩家10帧。在每次测试之前,我将设定某个框架的值,以适合我想要测试的内容。上面的测试是一个例子,我想确保在最后一帧的第三个碗上保龄球得分5正确地更新得分。但是,即使在调试器中,我发现在框架中更新了分数(当我在控制器方法中进行调试时),一旦我返回到Rspec测试,它不起作用。它预计25但得零。有什么我错过了实例变量如何在规格和控制器之间传输?

+0

如果您专注于一个案例并专门为该测试发布代码,那么您更有可能得到一个很好的答案,这样我们就有必要关注。发布链接到您的代码库的方式太开放了:发布您询问的特定案例的代码(即从第393行开始),所以我们不必去追捕它。 – 2013-05-02 06:14:40

+0

明白了 - 我添加了规范代码的特定片段。 – tanookiben 2013-05-02 08:26:46

回答

0

所以首先没有'转移'。控制器和示例是2个完全独立的对象,每个对象都有其自己的实例变量(您可以使用assigns规范助手来检索控制器实例变量的值)。

这不是你问题的根本原因。即使在控制器执行之前,您也可以拥有一个@game实例变量,这是您感兴趣的游戏。但是,使用activerecord时,每次执行Game.find时,都会收到单独的ruby对象(对应于相同的数据库行)。一旦从数据库加载该行,它就不会注意到其背后的数据库发生了更改。

可以重新装载@game.reload

对象作为一个方面说明这种东西是更容易,如果大部分逻辑被向下推入你的车型之一,而不是坐在控制器开始工作。