Disable STDOUT for tests

I write a lot of command line tools at Powerset, so I need to output status messages to the console while code is executing. Big deal, right? Well, it becomes a big deal once you run your test suite and you've got two hundred lines of status messages mixed in with the normal test output. I don't need to see console output during my tests. Here's a little method that will disable output to STDOUT for the duration of the block that it's given:

1
2
3
4
5
6
def no_stdout
 old_stdout = $stdout
 $stdout.reopen(File.open((PLATFORM =~ /mswin/ ? "NUL" : "/dev/null"), 'w'))
 yield
 $stdout = old_stdout
end

In your test, you'd call it like this:

1
2
3
4
5
def test_whatever
  no_stdout do
    puts 'no one will ever see this'
  end
end

This technique also works well for 3rd party libraries that might send some output to STDOUT that you don't want to see.

Sometimes, when I have a lot of output I need to do, I'll wrap puts and print in my own methods and call those from my code. This also allows me to add a $stdout.flush to make sure that the output is sent to the terminal immediately (some systems will buffer output up to a certain size, making those little progress meters useless):

1
2
3
4
5
6
7
8
9
10
class Base
  def out(text = '')
    print text
    $stdout.flush
  end

  def outs(text = '')
    out(text + "\n")
  end
end

Now instead of using the no_stdout method from above, I can simply redefine those methods to do nothing and all my output vanishes!

1
2
3
4
class Base
  def out(x); end
  def outs(x); end
end

Don't settle for crufty test output. We have the technology!


About this entry