簡體   English   中英

如何為包含包含“gets.chomp”的變量的 Ruby 方法編寫 Rspec 測試?

[英]How do I write an Rspec test for a Ruby method that contains variable that contains 'gets.chomp'?

我查看了其他測試示例,但大多數其他示例不一定有一個等於“gets.chomp.downcase”的變量,這讓我很難測試。

rest 用於國際象棋游戲,但我正在努力做到這一點,因此如果您在介紹中輸入“新”,它將調用方法#instructions,該方法會顯示說明並詢問您是否准備好下棋。

這是方法#introduction

def introduction
        puts " \n"
        print "     Welcome to chess! "
        puts "What would you like to do?"
        puts "

      * Start a new Game  ->  Enter 'new'
      * Load a saved Game ->  Enter 'load'

      * Exit              ->  Enter 'exit'"
      input = gets.chomp.downcase
      if input == "new"
        instructions
      elsif input == "load"
        load_game
      elsif input == "exit"
        exit!
      else 
        introduction
      end
    end

這是我對其進行的測試,它不斷顯示錯誤“失敗/錯誤:輸入=gets.chomp.downcase”

“NoMethodError:nil:NilClass 的未定義方法‘chomp’”

describe Game do
    describe "#introduction" do
        it "starts a new game with input 'new'" do

            io = StringIO.new
            io.puts "new"

            $stdin = io

            game = Game.new
            game.introduction
            allow(game).to receive(:gets).and_return(io.gets)

            expect(game).to receive(:instructions)
        end
    end
end

使用代碼注入代替模擬或存根

您的方法存在多個問題。 我不會一一列舉,而是關注三個關鍵錯誤:

  1. 單元測試通常應該測試方法結果,而不是復制內部。
  2. 您正在嘗試使用 #allow 而不首先定義雙精度。
  3. 您似乎正在嘗試設置消息期望,而不是使用存根返回值。

您的代碼和測試肯定還有其他問題,但是一旦您從測試用例中消除對#gets 的依賴,我就會從這里開始。 例如,要測試方法中的各種路徑,您可能應該為每個預期值配置一系列測試,其中 #and_return 顯式返回newload或其他。

更務實的是,您很可能會因為您先編寫代碼而苦苦掙扎,而現在正在嘗試進行 retrofit 測試。 雖然您可能會修補一些東西以使其事后可測試,但您最好重構代碼以允許在測試中直接注入。 例如:

def show_prompt
  print prompt =<<~"EOF"

    Welcome to chess! What would you like to do?

      * Start a new Game  ->  Enter "new"
      * Load a saved Game ->  Enter "load"
      * Exit              ->  Enter "exit"

    Selection:\s
  EOF
end

def introduction input=nil
  show_prompt

  # Use an injected input value, if present.
  input ||= gets.chomp.downcase

  case input
  when "new"  then instructions
  when "load" then load_game
  when "exit" then exit!
  else introduction
  end
end

這首先避免了存根或模擬 object 的需要。 您的測試現在可以簡單地調用帶有或不帶有顯式值的#introduction。 這使您可以花時間測試邏輯分支和方法輸出,而不是編寫大量腳手架來支持 IO#gets 調用的 mocking 或避免與 nil 相關的異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM