繁体   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