Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test output to command line with RSpec

I want to do is run ruby sayhello.rb on the command line, then receive Hello from Rspec.

I've got that with this:

class Hello
  def speak
    puts 'Hello from RSpec'
  end
end

hi = Hello.new #brings my object into existence
hi.speak

Now I want to write a test in rspec to check that the command line output is in fact "Hello from RSpec" and not "I like Unix"

NOT WORKING. I currently have this in my sayhello_spec.rb file

require_relative 'sayhello.rb' #points to file so I can 'see' it

describe "sayhello.rb" do
  it "should say 'Hello from Rspec' when ran" do        
    STDOUT.should_receive(:puts).with('Hello from RSpec')    
  end
end

Can someone point me in the right direction please?

like image 742
thefonso Avatar asked Jul 05 '12 17:07

thefonso


People also ask

How do I run a RSpec test in terminal?

Open your terminal, cd into the project directory, and run rspec spec . The spec is the folder in which rspec will find the tests. You should see output saying something about “uninitialized constant Object::Book”; this just means there's no Book class.

Is RSpec BDD or TDD?

RSpec is a testing tool for Ruby, created for behavior-driven development (BDD). It is the most frequently used testing library for Ruby in production applications. Even though it has a very rich and powerful DSL (domain-specific language), at its core it is a simple tool which you can start using rather quickly.

How do I run an RSpec on a specific file?

Running tests by their file or directory names is the most familiar way to run tests with RSpec. RSpec can take a file name or directory name and run the file or the contents of the directory. So you can do: rspec spec/jobs to run the tests found in the jobs directory.

Is RSpec used for unit testing?

RSpec is a unit test framework for the Ruby programming language. RSpec is different than traditional xUnit frameworks like JUnit because RSpec is a Behavior driven development tool.


3 Answers

Here's a pretty good way to do this. Copied from the hirb test_helper source:

def capture_stdout(&block)
  original_stdout = $stdout
  $stdout = fake = StringIO.new
  begin
    yield
  ensure
    $stdout = original_stdout
  end
  fake.string
end

Use like this:

output = capture_stdout { Hello.new.speak }
output.should == "Hello from RSpec\n"
like image 159
Casper Avatar answered Nov 15 '22 04:11

Casper


The quietly command is probably what you want (cooked into ActiveSupport, see docs at api.rubyonrails.org). This snippet of RSpec code below shows how to ensure there is no output on stderr while simultaneously silencing stdout.

quietly do                        # silence everything
  commands.each do |c|
    content = capture(:stderr) {  # capture anything sent to :stderr
      MyGem::Cli.start(c)
    }
    expect(content).to be_empty, "#{c.inspect} had output on stderr: #{content}"
  end
end
like image 23
Joe Goggins Avatar answered Nov 15 '22 04:11

Joe Goggins


So you don't have to change your main ruby code I just found out you can do something like this:

def my_meth
  print 'Entering my method'
  p 5 * 50
  puts 'Second inside message'
end

describe '#my_meth' do
  it 'puts a 2nd message to the console' do
    expect{my_meth}.to output(/Second inside message/).to_stdout
  end
end

When checking for a desired output text I used it inside / / like a Regexp because after many many maaany tests and looking around, the STDOUT is everything that is outputted so I found it to be better to use Regex so you could check the whole STDOUT for the exact text that you want. Like I put it, it works in the terminal just perfect.

//Just had to share this, it took me days to figure it out.

like image 31
Alfredo C. Avatar answered Nov 15 '22 05:11

Alfredo C.