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

Testing program that runs with user input from the console

我正在为一个模拟电梯的系统编写测试。例如,我想测试电梯是否可以改变方向,是否可以移动到指定楼层。

我有以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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后检查它的值是否改变。

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

如何通过move方法模拟从一开始(Elevator.new.arrival运行的程序,并将其停止在那里,这样我就可以在不运行程序本身和使用IO管道模拟用户交互的情况下检查@current_floor的值——所有这些都是如此?

我有一种感觉,我可能以错误的方式设计了程序。如果有人能给我指明解决这个问题的正确方向,我会感激的。

编辑

根据魔杖制造者的建议,我编写了一个测试,如下所示:

1
2
3
4
5
6
7
8
9
10
11
  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,但我想不出别的办法。


这就回答了你问题的这一部分:我如何通过move方法模拟程序从一开始(lifter.new.arrival)运行,并将其停止,以便检查@current_floor的值?

  • 安装方式:gem install byebug
  • 在你的档案中要求:require 'byebug'
  • 在要停止程序的地方添加byebug命令,例如在move的开头(参见文章末尾的代码)。
  • 您被放入一个shell中,可以通过键入来检查所有内容,例如@current_floor,或者通过使用self来检查实例。
  • 如果您想继续,点击CTRL+D,程序将继续(您可能做过的任何修改)。
  • 这将帮助您调试它。

    1
    2
    3
    4
    5
    6
    7
    8
    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

    如此答案所示,您可以重写getvalue以输入用户输入。

    这里有一个完整的代码,可以在不实际使用gets的情况下工作。我不得不添加一些缺失的方法-validate_floor_numberfinal_destination

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    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

    以上程序输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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]