1

I'm looking for some help outputting the activity messages into the command line window. I know this may seem backwards but this is the task I've been given. I've already written tests so that they all pass but I need to convert the below activity into the command line window. It's just a game that resembles the Impossible Machine game.

Firstly I need to create a process which starts the Impossible Machine, then simulate each of the activities being initiated in succession before finishing.

Of what I understand, all the messages displayed should be sent to the STDOUT channel. These are some of the tests that have been written:

module ImpossibleMachine
# Input and output constants processed by subprocesses
DOWN_ARROW = 1
UP_ARROW = 2
RIGHT_ARROW = 3
REPEAT_ARROW = 4
END_PROCESS = 5 
START_CURRENT = 6

# RSpec Tests 
describe Game do
    describe "#start The impossible machine game" do
        before(:each) do
            @process = []
            @output = double('output').as_null_object
            @game = Game.new(@output)
        end
        it "sends a welcome message" do
            @output.should_receive(:puts).with('Welcome to the Impossible Machine!')
            @game.start
        end
        it "should contain a method created_by which returns the students name" do
            myname = @game.created_by
            myname.should == "My Name"
        end
        it "should perform lifts_lever_turns_wheel activity which returns REPEAT_ARROW" do
            @output.should_receive(:puts).with("Input: #{UP_ARROW}, Activity: Heave_ho_squeek_squeek")
            @process[1] = @game.lifts_lever_turns_wheel(UP_ARROW)
            @process[1].should == REPEAT_ARROW
        end
        it "sends a finishing message" do
            @output.should_receive(:puts).with('...Game finished.')
            @game.finish            
        end
    end
end

My only knowledge is that I need to start the module like this and then proceed to add code below it so that it outputs the activity messages to the command line:

module ImpossibleMachine
@process = []
g = Game.new(STDOUT)

Hope that makes sense.

samgbelton
  • 89
  • 1
  • 10
  • Does this answer your question? [Testing STDOUT output in Rspec](https://stackoverflow.com/questions/16507067/testing-stdout-output-in-rspec) – TonyArra Apr 13 '22 at 17:15

2 Answers2

1

It is not very clear from your question - you want the game to show its output to STDOUT when you run the rspec?

If this is the case, I'll explain why in your code as you post it, it does not happen:

When you create the new game @game you create it with Game.new(@output). The @output is a double, which means that it is not really an output object at all, but it is a mock object instead.

This is totally fine, by the way. The only problem with it is that it doesn't actually print anything to the console.

If you want to make the tests, while actually printing to the console, you should pass the actual STDOUT object:

before(:each) do
  @process = []
  @output = STDOUT
  @game = Game.new(@output)
end

This will almost work, as it will print all messages except the ones you stub in your tests @output.should_receive(...). To make those work, you should add and_call_original to each expectation:

@output.should_receive(:puts).with('Welcome to the Impossible Machine!').and_call_original
Uri Agassi
  • 36,848
  • 14
  • 76
  • 93
  • Thanks but not quite, I want the game to run the output to STDOUT when run you run a new ruby file. I know that ruby file begins with the 3 lines of code above but I do not know what comes below that. So in other words, I need to create some new lines of code below those 3 lines that will create a process which starts the Impossible Machine, then simulate each of the activities being initiated in succession before finishing. But I do not know where to start... – samgbelton Apr 29 '14 at 08:47
  • Hard as I might, I can't seem to understand what exactly you need. What file? Which process? I don't know what is _in_ the `Game` class or what does `@process` do... – Uri Agassi Apr 29 '14 at 13:22
  • Don't worry, I've fixed it now. What I needed was to output the messages in a process like: @process(0) = g.lifts_lever_turns_wheel(2) etc. Thanks anyway! – samgbelton Apr 29 '14 at 13:26
0

You can do this without doubles:

  it "should perform lifts_lever_turns_wheel activity which returns REPEAT_ARROW" do
    expect(STDOUT).to receive(:puts).with("Input: #{UP_ARROW}, Activity: Heave_ho_squeek_squeek")
    @process[1] = @game.lifts_lever_turns_wheel(UP_ARROW)
    @process[1].should == REPEAT_ARROW
  end
David Hempy
  • 5,373
  • 2
  • 40
  • 68
  • I'm not sure why you revived two dead questions to give this answer, but RSpec also has a built-in matcher for this now. So you don't need doubles. https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/output-matcher – TonyArra Apr 12 '22 at 18:57
  • Why? To share another solution to this question, of course. Thanks for teaching me about the `output` matcher, @TonyArra. I'll add that as yet-another-solution to both these old questions. – David Hempy Apr 13 '22 at 14:14