Testing & stdout

M

Miki Tebeka

Hello All,

In my test suite I also test some function that output messages to stdout.
Is there an easy way to temporary divert stdout to another location?

Currently I'm using:

import sys
from StringIO import StringIO
from unittest import TestCase, main

def with_io_divert(func):
'''Divert stdout'''
orig = sys.stdout
io = StringIO()
sys.stdout = io
try:
func(io)
finally:
sys.stdout = orig

def io_clear(io):
'''Clear io'''
io.seek(0)
io.truncate()

def io_value(io):
'''Value in io'''
return io.getvalue().strip()

class SomeTest(TestCase):
def test_print(self):
def func(io):
msg = "Alice had a little lamb"
print msg
self.assertEqual(io_value(io), msg)

with_io_divert(func)

if __name__ == "__main__":
main()


This works fine if no one is caching stdout somewhere.

TIA.

Miki.
 
P

Peter Hansen

Miki said:
In my test suite I also test some function that output messages to stdout.
Is there an easy way to temporary divert stdout to another location?

Currently I'm using: [snip]
This works fine if no one is caching stdout somewhere.

"Caching stdout"? What's that mean? Who would do such a thing?

Normally issues like this would have an answer "use flush()", but with
the example you gave, where you're diverting output directly to a StringIO,
I can't see how that would help. I also can't see why it would be needed.

If you have code which is actually holding back output which it will
eventually write to stdout (is that what "caching stdout" means here?)
then obviously diverting stdout to a StringIO is going to do nothing
useful for you in your unit tests.

I think you need to explain more or something... sorry.

-Peter
 
J

John Roth

Miki Tebeka said:
Hello All,

In my test suite I also test some function that output messages to stdout.
Is there an easy way to temporary divert stdout to another location?

You can, I believe, replace the stdout object in the builtins directory
with one that does what you need it to do. Remember to restore it
when you're done. Python keeps the original value of stdout somewhere,
but that doesn't help if your application also replaces and restores it.

John Roth
 
P

Peter Hansen

Peter said:
Miki said:
In my test suite I also test some function that output messages to stdout.
Is there an easy way to temporary divert stdout to another location?

Currently I'm using: [snip]
This works fine if no one is caching stdout somewhere.

"Caching stdout"? What's that mean? Who would do such a thing?

Ah, reading John's reply I think I figured out what you meant.
You mean some of the code being called is using a saved reference
to sys.stdout, and so it won't dynamically pick your changed version
of that name.

I encountered the same problem once, and found no solution.

-Peter
 
J

John Roth

Peter Hansen said:
Peter said:
Miki said:
In my test suite I also test some function that output messages to stdout.
Is there an easy way to temporary divert stdout to another location?

Currently I'm using: [snip]
This works fine if no one is caching stdout somewhere.

"Caching stdout"? What's that mean? Who would do such a thing?

Ah, reading John's reply I think I figured out what you meant.
You mean some of the code being called is using a saved reference
to sys.stdout, and so it won't dynamically pick your changed version
of that name.

I encountered the same problem once, and found no solution.

Good point. If he's using unittest, it's a problem in only one case:
where the cached reference is at the module level. Otherwise,
each unit test starts fresh.

If it's at the module level, then the unit test suite has to do something
different. I'd fix the offending module, but possibly he isn't using
XP, so he can't do that.

John Roth
 
M

Miki Tebeka

Hello John,
Yes. Sorry I wasn't clear the 1'st time.
:-(

Good point. If he's using unittest, it's a problem in only one case:
where the cached reference is at the module level. Otherwise,
each unit test starts fresh.
To eliminate this problem you can always find the problematic module
and do a "reload" at the TestCase "setUp" function. However this
requiers you to track down all offending modules, which is error
prone.
If it's at the module level, then the unit test suite has to do something
different. I'd fix the offending module, but possibly he isn't using
XP, so he can't do that.
XP as in eXtreme Programming? What's the connection?

Miki
 
J

John Roth

Miki Tebeka said:
Hello John,

Yes. Sorry I wasn't clear the 1'st time.

To eliminate this problem you can always find the problematic module
and do a "reload" at the TestCase "setUp" function. However this
requiers you to track down all offending modules, which is error
prone.
XP as in eXtreme Programming? What's the connection?

Shared code ownership. The classical model says the tester writes
up a report and gets frustrated. The XP model says that if you find
it hard to test, you find a developer, sit down with him and fix it
so you can test it.

John Roth
 
M

Miki Tebeka

Hello John,
Shared code ownership. The classical model says the tester writes
up a report and gets frustrated. The XP model says that if you find
it hard to test, you find a developer, sit down with him and fix it
so you can test it.
OK.
Since I wear both hats (coding & testing) it's not an issue.

Miki
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,169
Messages
2,570,920
Members
47,462
Latest member
ChanaLipsc

Latest Threads

Top