我在使用minitest為Ruby中一個呼叫自身的方法(一個游戲回圈)開發單元測驗時遇到了困難。我所嘗試的是用我的輸入來存根我試圖在上述游戲回圈中呼叫的方法。以下是游戲回圈:
#main game loop。
def playRound
#draw board
@board.printBoard
#get input
playerInput = gets.chomp #returns user input without ending newline[/span]。
#解釋輸入,退出或開始選擇玩家的設定。
case playerInput
when "q"/span>
退出
when "a"/span>, "l"/span>
set = getPlayerSet()
if(playerInput == "a")
玩家=1
else[/span]。
player = 2
end
when "h"
if @hintsEnabled
給予提示
播放回合
else
放置"提示被禁用"。
回圈播放
結束。
else
放置"未識別輸入。"
結束。
if(set != nil)
#have board test set(set!
checkSet(set, player)
結束。
#check if player has quitted or there are no more valid sets[/span].
unless @quitted || @board.boardComplete
播放回合
結束。
結束。
很多東西最終都是無關緊要的,我所要測驗的是這個switch陳述句正在呼叫正確的方法。目前,我正試圖通過存根被呼叫的方法來引發一個錯誤(我的測驗assers_raise的)來規避這個回圈:
def test_playRound_a_input_triggers_getPlayerSet<
@game.stub :getPlayerSet, raise(StandardError) do.
assert_raises(StandardError)do。
simulate_stdin(""/span>) {
@game.playRound
}
end。
結束。
end end
然而,這種方法似乎并不奏效,因為Minitest將上述測驗的結果記錄為錯誤,資訊為
。E
錯誤:
TestGame#test_playRound_a_input_triggers_getPlayerSet:
標準錯誤。標準錯誤
test_game.rb:136:in `test_playRound_a_input_triggers_getPlayerSet'
如果有人給我任何建議或指導,我將不勝感激,因為我不知道哪里出了問題
。uj5u.com熱心網友回復:
我對minitest不是很熟悉,但我希望你需要將raise(exception)包裹在一個塊中,否則你的測驗代碼會在你的測驗中立即引發例外(而不是作為存根方法被呼叫的結果)。
比如說:
class CustomTestError < RuntimeError; end
def test_playRound_a_input_triggers_getPlayerSet
raise_error = -> { raise(CustomTestError) }
@game.stub(:getPlayerSet, raise_error) do.
assert_raises(CustomTestError) do
simulate_stdin(""/span>) {
@game.playRound
}
end。
結束。
end end
--編輯--
有時候,當我在測驗一個方法時遇到困難,這說明我應該重構一些東西,使之更容易測驗(從而有一個更干凈、更簡單的界面,以后可能更容易理解)。
我不撰寫游戲代碼,也不知道游戲回圈的典型情況,但該方法看起來非常難以測驗。我將嘗試把它分成幾個步驟,每個步驟/命令都可以很容易地被單獨測驗。一個選擇是為每個命令定義一個方法并使用send。這將使你能夠測驗每個命令是否與你的輸入決議和游戲回圈本身分開作業。
COMMANDS = {
q: : quit,
# etc.。
}.stringify_keys.freeze
def play_round # Ruby方法應該是snake_case而不是camelCase。
@board.print_board
run_command(gets.chomp)
play_round unless @quitted || @board.board_complete
結束。
def run_command(input)
command = parse_input_to_command(input)
run_command(command)
end
def parse_input_to_command(輸入)
COMMANDS[輸入] || :bad_command
結束
def run_command(命令)
send("run_#{command}")
結束。
# Then a method for each command, e.g.
def run_bad_input
放置"輸入不被識別"。
end
然而,對于這種型別的問題,我真的很喜歡功能化的方法,每個命令只是一個無狀態的函式,你將狀態傳入并獲得新的狀態回傳。這些函式可以改變他們的輸入狀態(惡心),或者回傳一個具有更新狀態的棋盤的新副本(好耶!)。比如說:
COMMANDS = {
# 所有的狀態變化都必須在船上完成。為了成為一個功能模式,你不應該改變板子,而應該回傳一個新的。為此,我發明了一個`.copy()`方法,它將更新的屬性作為輸入。
q: -> {|board| board.copy(quitted: true) },
h: -> HintGiver.new, # 如果這些命令很復雜,它們可以完全住在一個單獨的類中。
bad_command: -> {|board| puts "Unrecognized command"; board },
#; board }.
}.stringify_keys.freeze
def play_round
@board.print_board
command = parse_input_to_command(gets.chomp)
@board = command.call(@board)
play_round unless @board.quitted || @board.board_complete
結束。
def parse_input_to_command(input)
COMMANDS[輸入] || COMMANDS[:bad_command]
結束。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/323809.html
標籤:
