Various behaviors of doctest

G

Gnarlodious

Using the doctest module, I get three different outputs:

1) From the Terminal shell, I see a full report:
python ~/Sites/Sectrum/Filter.py -v

2) From the Terminal interactive session, I see an abbreviated report
of only the failures:
from doctest import testmod; testmod(Filter)

3) From a browser CGI, I see a named tuple:
from doctest import testmod; doctest.testmod()

This returns output like:

TestResults(failed=1, attempted=5)

The browser is invoking the exact same code as the shell doctest, so
why should it return a named tuple? And how do I get it to return the
full text so I can read it in the browser?

-- Gnarlie
 
S

Steven D'Aprano

Using the doctest module, I get three different outputs:

1) From the Terminal shell, I see a full report:
python ~/Sites/Sectrum/Filter.py -v

Can we assume that Filter.py, whatever that is, runs doctest.testmod()?


2) From the Terminal interactive session, I see an abbreviated report of
only the failures:
from doctest import testmod; testmod(Filter)

That's because you haven't specified the verbose option, either by
injecting -v into sys.argv, or by verbose=True as an argument to testmod.

3) From a browser CGI, I see a named tuple: from doctest import testmod;
doctest.testmod()

This returns output like:

TestResults(failed=1, attempted=5)

The browser is invoking the exact same code as the shell doctest, so why
should it return a named tuple?

Because testmod *always* returns a named tuple. Read the Fine Manual at
the interactive interpreter with:

help(testmod)

And how do I get it to return the full
text so I can read it in the browser?

You don't. Consider a simplified version:

def testmod():
print "lots of stuff"
return (failures, total)


If you want to capture "lots of stuff", you have to either play nasty
tricks with replacing standard out with a StringIO instance, or similar,
or you have to look at the implementation of testmod() and re-implement
it yourself.

Oh, here's a thought, if you're running Python 3, you could monkey-patch
doctest:


# COMPLETELY UNTESTED!!!

from stringio import StringIO
from functools import partial
buffer = StringIO()
myprint = partial(print, file=buffer)
doctest.print = myprint

doctest.testmod()

Now somehow you have to pass buffer.as_string() to your CGI program, in
whatever way you would normally do so.
 
G

Gnarlodious

Yeah, I just spent about 2 hours trying everything I could think of...
without success. Including your suggestions. Guess I'll have to skip
it. But thanks for the ideas.

-- Gnarlie
 
P

Peter Otten

Gnarlodious said:
Yeah, I just spent about 2 hours trying everything I could think of...
without success. Including your suggestions. Guess I'll have to skip
it. But thanks for the ideas.

-- Gnarlie

Are you using Python 2.x? Then you cannot redefine print. Instead you have
to redirect stdout. The following example should run as a cgi script:

#!/usr/bin/env python
import cgi
import sys
from cStringIO import StringIO

def f():
"""'<'
"""

if __name__ == "__main__":
print ("Content-type: text/html\r\n\r\n"
"<html><body style='background-color:#f0f0f0'>"
"<h1 style='color: navy;'>There goes:</h1>")

outstream = StringIO()
import doctest, sys

from doctest import DocTestRunner
class DTR(DocTestRunner):
def run(self, test, compileflags=None, out=None, clear_globs=True):
DocTestRunner.run(self, test, compileflags, outstream.write,
clear_globs)
def summarize(self):
saved = sys.stdout
sys.stdout = outstream
DocTestRunner.summarize(self)
sys.stdout = saved

doctest.DocTestRunner = DTR
doctest.testmod(verbose=True)
text = outstream.getvalue()

for line in text.splitlines():
spaces = len(line) - len(line.lstrip())
line = line.strip()
if "*****" in line:
print "<hr/>"
else:
print "<div style='color: %s; margin-left:%sem;'>%s</div>" % (
"blue" if spaces else "black", spaces, cgi.escape(line))
print "</body></html>"
 
G

Gnarlodious

Are you using Python 2.x? Then you cannot redefine print. Instead you have
to redirect stdout. The following example should run as a cgi script:

#!/usr/bin/env python
import cgi
import sys
from cStringIO import StringIO
....

That works! Except for Py3 I had to say:

from io import StringIO

Thanks.

-- Gnarlie
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top