2013-05-02 2 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 행)를 게시하여 사냥을 할 필요가 없습니다. –

+0

알았습니다 - 스펙 코드의 특정 스 니펫을 추가했습니다. – tanookiben

답변

0

먼저 '전송'이 없습니다. 컨트롤러와 예제는 2 개의 완전히 독립적 인 객체이며 각 인스턴스에는 자체 인스턴스 변수가 있습니다 (assigns spec helper를 사용하여 컨트롤러 인스턴스 변수의 값을 검색 할 수 있습니다).

문제의 근본 원인이 아닙니다. 컨트롤러가 실행되기 전에도 관심있는 게임 인 인스턴스 변수가 @game입니다. 그러나 activerecord를 사용하면 Game.find을 실행할 때마다 별도의 루비 객체 (동일한 데이터베이스 행에 해당)가 수신됩니다. 행이 데이터베이스에서로드되면 데이터베이스의 변경 사항을 알 수 없습니다.

당신은 물건의 종류가 대부분의 논리가 아니라 컨트롤러에 앉아보다 당신의 모델 중 하나에 푸시 다운 된 경우 작업하기 쉬운 측면 참고로 @game.reload

와 객체를 다시로드 할 수 있습니다.

관련 문제