[py-dev] Backtracking on doctest

Ian Bicking ianb at colorstudy.com
Fri May 13 22:00:16 CEST 2005


holger krekel wrote:
> On Fri, May 13, 2005 at 14:00 -0500, Ian Bicking wrote:
> 
>>Well, now I'm starting to backtrack.  After I extended my test while 
>>adding new features, I looked back over my doctests and realized they 
>>were pretty pointless.  For brevity, most of my code no longer produced 
>>output at all, but instead was doing internal inserts.  If I didn't have 
>>a wrapper around my application for testing this might not have been 
>>feasible, but without a wrapper the testing wouldn't be feasible.
> 
> 
> Interesting.  With PyPy we noticed that we have lots of problems
> with some doctest/output-comparison related CPython regression 
> tests.  Doctests and output-comparisons are pretty sensitive 
> to the exact way things are represented as strings.  Nevertheless
> i still like the general doctest idea. 

It's not too terribly hard to override the comparison that doctest does. 
  Personally I like fuzzier comparisons in general.  There's not a very 
good way to install those comparisons, so if py.test integrates doctest 
it would be nice to have a convention for that.

For instance, for HTML-generating code I've written code to do more 
semantic XML comparisons that ignore some whitespace and the order of 
attributes.

>>Anyway, I converted it to a normal py.test test.  It seems much more 
>>reasonable.  I'm a little sad that it's not sitting right next to the 
>>servlet that it tests -- I liked that the tests were in a docstring 
>>(though they were also becoming rather long-winded, so maybe that's not 
>>ultimately practical either).  
> 
> 
> Did you consider putting tests in the same source file as the code
> being tested?  It's probably often not too nice but i am using it
> for one-file scripts and simply invoke 'py.test myscript.py'. 

I had, but I'm not sure if it would help a lot.  I'd still need the 
hooks in conftest, because I'd wanted those tests to be automatically 
picked up.  If it's just a function at the bottom of the module, I don't 
think that's actually much better than a separate module.

I think I had this idea that I could put ten lines of doctest at the top 
of my module that would be this concise documentation and description of 
the module, plus a test.  I'm not sure that's feasible, though it is 
still possible to use that for basic exercising of the code -- basically 
a one-liner that tells what a valid URL would be.  And, maybe, with a 
subclass of the standard Paste fixture you could add things like:

   app.upload_csv([('Name', 'Email'), ('Bob', 'bob at company.com')])

And that could be high enough level to get some benefit from being in a 
docstring.  But those kinds of methods (like "upload_csv") would have to 
be implemented in a class specifically meant for testing a single 
screen; which is also a useful idea, but I haven't really gotten that 
far in generalizing this stuff.

>>setup_module turned out to be quite useful; I added this to my conftest, 
>>and do a "from conftest import setup_module" in my module:
>>
>>def setup_module(module):
>>    app = TestApp(server.make_app(CONFIG.current_conf()),
>>                  CONFIG.current_conf())
>>    module.app = app
>>    module.CONFIG = CONFIG
>>    fixture.reset_state()
> 
> 
> I guess we should start a "recipe" section in the
> documentation for nice ideas like this.    

Once I get this all figured out I'll probably document the entire 
process for Paste, and include this code somewhere in the project.

> Btw, i once thought about making your above
> conftest.setup_module(module) get invoked automagically just
> like Collectors/Items are looked up.  An advantage could be
> that you could stack setup_module initializations but i am not
> sure how useful that is (it might be for larger projects).
> It's easy to add this feature should we want it. 

I could speculate, but I should probably keep trying to implement tests 
and then figure out what's works and what feels awkward.  Since I only 
have one module tested so far, "boilerplate" in that one module is no 
worse than a line of code in conftest ;)

>>I think it's likely that other boilerplate stuff will go in there in the 
>>future.  I'd still like doctests to work nicely, but it becomes less 
>>important to me.
>>
>>Anyway, no requests here, just thought I'd share my current and always 
>>changing thoughts on the matter.
> 
> 
> Thanks a lot.  I admit that your "ravioli" term used earlier deeply 
> hurt my feelings until i realized that you didn't say Spaghetti :-) 

Heh, sorry ;)  It's a term I came upon one day on the wiki 
(http://c2.com/cgi/wiki?RavioliCode) and it kind of stuck in my mind as 
a useful metaphor, but I forget that no one else knows what I mean.  If 
I had read up and knew what method to start looking at, I'd probably 
wouldn't have felt that way -- though it's always a risk with 
dynamically typed code, because in isolation it can be hard to tell what 
object you are interacting with.  For instance, I had a hard time 
figuring out when a variable was the object itself, or its collection 
wrapper (e.g., collect.Module or the actual module object).

-- 
Ian Bicking  /  ianb at colorstudy.com  /  http://blog.ianbicking.org



More information about the Pytest-dev mailing list