[TIP] Generating tests, II (was: Re: Meta-test methods...)
C. Titus Brown
ctb at msu.edu
Fri Apr 24 11:32:55 PDT 2009
On Fri, Apr 24, 2009 at 12:01:35AM -0400, Douglas Philips wrote:
-> On 2009 Apr 23, at 9:45 AM, C. Titus Brown wrote:
-> > On Thu, Apr 23, 2009 at 09:06:42AM -0400, Douglas Philips wrote:
-> > -> On or about 2009 Apr 23, at 1:14 AM, C. Titus Brown indited:
-> > -> > Anyway, I double-dare you to make this:
-> > -> >
-> > -> > http://github.com/ctb/figleaf/blob/d11d2ee0ce70427b229af15409bff2ab23e090d2/tests/test_regress/__init__.py
-> > -> >
-> > -> > work nicely without decorators.
-> > ->
-> > -> ??? With decorators, you mean?
-> > Sorry: generators.
-> Anyway, I double-dare you pay attention to the issue at hand. :)
-> I never said generators were bad.
Ahh, sorry, my misunderstanding.
-> I said that checking a test method
-> for being a generator was a hack, seeminly cool at first, but upon
-> further thought it is just as a proof of concept that it is useful to
-> have a way to dynamically generate a sequence of test methods/functions.
-> Testing only for generators is both opaque and, critically, fails to
-> generalize to arbitrary python sequences.
This might be a discussion better carried out on nose-dev, but:
isn't one issue that generators are the only "iterator-like" function to
have a clear signature at the time of definition? Specifically, how
else can I know that a test_* function was a test generator rather than
a function executing a single test?
'yield' makes the function have a generator type, which is kind of cool
to realize -- I hadn't thought of yield as being an implementation of
function typing in Python before ;)
Anyway, I can't think of a way to write a wrapper that would be able to
make that distinction for your code below without actually running the
function and trying to iterate over what it returned. That might be the
reason why nose does things the way it does.
-> It is rather foolish to post my version, since you have not disclosed
-> your criteria of "nicely"...
-> none-the-less, off the cuff, I find this to be slightly nicer. And
-> while you don't state your criteria, I will say that I think this is -
-> slightly- nicer because it reduces the level of nesting (Flatter is
-> better than nested) and gives meaningful names to the concepts involved.
-> def test_source_generator():
-> is_test_file = lambda name: name.startswith('tst') and
-> pair_up = lambda name: (compare_coverage, file)
-> return map(pair_up, filter(is_test_file, os.listdir(testdir))
As you say, now we're getting into personal coding style, but I
generally try to avoid map/filter and lambdas; it provides terseness at
the expense of clarity. YMOV ;)
C. Titus Brown, ctb at msu.edu
More information about the testing-in-python