I'm writing tests for a system that models an elevator. For example, I want to test that the elevator can change direction and that it can move to a specified floor.
I have the following methods:
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
I start the program by calling Elevator.new.arrival
. To check that the elevator has changed directions, I need to store the value of @current_floor
in a temporary variable then check it's value has changed after move
has been called.
I am testing input from the console using an IO pipe thanks to the answers in this question, but I'm not sure how to apply that knowledge to user interaction that's part of a method.
How can I simulate the program running from the start (Elevator.new.arrival
) through the move
method and stop it there so I can check the value of @current_floor
- all of this without running the program itself and using the IO pipe to simulate user interaction?
I have a feeling that I might have gone about the design of the program in the wrong way. If anyone can even point me in the right direction towards solving this problem I'd appreciate it.
Edit
According to the suggestions from Wand Maker I've written a test as follows:
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
Unfortunately, when I run my test file, the program still runs and prompts for user input. Maybe I'm calling arrival
incorrectly but I can't think of another way to do it.
As demonstrated in this answer, you can override
getvalue
to feed in the user input.Here is complete code that works without actually using
gets
. I had to add couple of missing methods -validate_floor_number
andfinal_destination
:Output of above program:
This answers this part of your question: How can I simulate the program running from the start (Elevator.new.arrival) through the move method and stop it there so I can check the value of @current_floor?
gem install byebug
require 'byebug'
byebug
command where you want to stop your program, for example at start ofmove
(see code at the end of the post)@current_floor
by typing it out, or the instance by usingself
CTRL+D
and the program will continue (with any modification you might have done)That should help you debugging it.