使用来自控制台的用户输入运行的测试程序

Testing program that runs with user input from the console

我正在为模拟电梯的系统编写测试。比如我要测试电梯可以变向,可以移动到指定楼层。

我有以下方法:

def initialize
  @current_floor = 0
  @requested_floor = 0
end
def get_value
  gets.chomp
end
def arrival
  print "Enter floor number: "
  @requested_floor = get_value
  # only proceed if user entered an integer
  if validate_floor_number(@requested_floor)
    @requested_floor = @requested_floor.to_i
    move
  else
    arrival
  end
end
def move
  msg = ""
  @current_floor < @requested_floor ? msg = "Going Up!" : msg = "Going Down"
  puts msg
  @current_floor = @requested_floor
  next_move
end
def next_move
  puts "Do you want to go to another floor? Y/N"
  another_floor = (get_value).upcase
  another_floor == 'N' ? final_destination : arrival
end

我通过调用 Elevator.new.arrival 启动程序。要检查电梯是否改变了方向,我需要将 @current_floor 的值存储在一个临时变量中,然后在 move 被调用后检查它的值是否发生了变化。

由于 this question 中的答案,我正在使用 IO 管道测试来自控制台的输入,但我不确定如何将这些知识应用于作为方法一部分的用户交互。

如何通过 move 方法从一开始 (Elevator.new.arrival) 模拟程序 运行ning 并 在那里停止它 所以我可以检查 @current_floor 的值 - 所有这些都不需要 运行 程序本身并使用 IO 管道来模拟用户交互?

我觉得我可能以错误的方式进行了程序设计。如果有人能指出我解决这个问题的正确方向,我将不胜感激。

编辑

根据Wand Maker的建议,我写了一个测试如下:

  describe "checks that the elevator can change directions" do
    before do
      moves = [3, 'Y', 5, 'Y', 2, 'Y', 7, 'N']
      def get_value; moves.next end
    end

    it "should stop on floor 7" do
      Elevator.new.arrival
      assert_equal(@current_floor, 7)
    end
  end

不幸的是,当我 运行 我的测试文件时,程序仍然 运行 并提示用户输入。也许我调用 arrival 不正确,但我想不出另一种方法。

this answer 中所示,您可以覆盖 getvalue 以提供用户输入。

这是无需实际使用 gets 即可运行的完整代码。我不得不添加几个缺失的方法 - validate_floor_numberfinal_destination:

require 'minitest/autorun'

class Elevator
  attr_accessor :current_floor

  def initialize
    @current_floor = 0
    @requested_floor = 0
    #@last_floor = false
  end

  def get_value
    gets.chomp
  end

  def validate_floor_number(v)
    v.to_i rescue false
  end

  def arrival
    print "Enter floor number: "
    @requested_floor = get_value

    # only proceed if user entered an integer
    if validate_floor_number(@requested_floor)
      @requested_floor = @requested_floor.to_i
      move
    else
      arrival
    end
  end

  def move
    msg = ""
    @current_floor < @requested_floor ? msg = "Going Up!" : msg = "Going Down"
    puts msg
    @current_floor = @requested_floor
    next_move
  end

  def final_destination 
    puts "Reached your floor"
  end

  def next_move
    puts "Do you want to go to another floor? Y/N"
    another_floor = (get_value).upcase
    another_floor == 'N' ? final_destination : arrival
  end

 end 

 describe "checks that the elevator can change directions" do
    before do
      class Elevator
          @@moves = [3, 'Y', 5, 'Y', 2, 'Y', 7, 'N'].each
          def get_value; @@moves.next end
      end
    end

    it "should stop on floor 7" do
      e = Elevator.new
      e.arrival
      assert_equal(e.current_floor, 7)
    end
 end

以上程序的输出:

Run options: --seed 2561

# Running:

Enter floor number: Going Up!
Do you want to go to another floor? Y/N
Enter floor number: Going Up!
Do you want to go to another floor? Y/N
Enter floor number: Going Down
Do you want to go to another floor? Y/N
Enter floor number: Going Up!
Do you want to go to another floor? Y/N
Reached your floor
.

Finished in 0.001334s, 749.4982 runs/s, 749.4982 assertions/s.

1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
[Finished in 0.3s]

这回答了你问题的这一部分:我如何通过移动方法[=]从一开始(Elevator.new.arrival)模拟程序运行 23=] 然后停在那里,这样我就可以检查 @current_floor?

的值
  1. 安装 byebug:gem install byebug
  2. 在您的文件中需要它:require 'byebug'
  3. 在您想要停止程序的地方添加 byebug 命令,例如在 move 的开头(参见 post 末尾的代码)
  4. 您将进入 shell 并可以检查所有内容,例如 @current_floor 通过键入它,或通过使用 self
  5. 来检查实例
  6. 如果您想继续,请点击 CTRL+D 程序将继续(您可能已进行任何修改)

这应该可以帮助您调试它。

def move
  byebug # <-- program will stop here
  msg = ""
  @current_floor < @requested_floor ? msg = "Going Up!" : msg = "Going Down"
  puts msg
  @current_floor = @requested_floor
  next_move
end