[Python-Dev] Python equivalents in stdlib Was: Include datetime.py in stdlib or not?

Brett Cannon brett at python.org
Thu Jul 8 21:18:17 CEST 2010


On Thu, Jul 8, 2010 at 07:59, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On Thu, Jul 8, 2010 at 9:13 AM, Benjamin Peterson <benjamin at python.org> wrote:
>> 2010/7/7 Nick Coghlan <ncoghlan at gmail.com>:
>>> On Thu, Jul 8, 2010 at 7:56 AM, Michael Foord <fuzzyman at voidspace.org.uk> wrote:
>>>> Using a class decorator to duplicate each _test_ into two test_* methods
>>>> sounds  like a good approach.
>>>
>>> Note that parameterised methods have a similar problem to
>>> parameterised modules - unittest results are reported in terms of
>>> "testmodule.testclass.testfunction", so proper attribution of results
>>> in the test output will require additional work. The separate
>>> subclasses approach doesn't share this issue, since it changes the
>>> value of the second item in accordance with the module under test.
>>
>> A good parameterized implementation, though, gives the repr() of the
>> parameters in failure output.
>
> That would qualify as "additional work" if your tests aren't already
> set up that way (and doesn't cover the case of unexpected exceptions
> in a test, where the test method doesn't get to say much about the way
> the error is reported).
>
> I realised during the day that my suggested approach was more
> complicated than is actually necessary - once the existing tests have
> been moved to a separate module, *that test module* can itself be
> imported twice, once with the python version of the module to be
> tested and once with the C version. You can then do some hackery to
> distinguish the test classes without having to modify the test code
> itself (note, the below code should work in theory, but isn't actually
> tested):
>
> =============
> py_module_tests = support.import_fresh_module('moduletester',
> fresh=['modulename'], blocked=['_modulename'])
> c_module_tests = support.import_fresh_module('moduletester',
> fresh=['modulename', '_modulename'])
>
> test_modules = [py_module_tests, c_module_tests]
> suffixes = ["_Py", "_C"]
>
> for module, suffix in zip(test_modules, suffixes):
>    for obj in module.itervalues():
>        if isinstance(obj, unittest,TestCase):
>            obj.__name__ += suffix
>            setattr(module, obj.__name__, obj)
>
> def test_main():
>    for module in test_modules:
>        module.test_main()
> =============

Very cool solution (assuming it works =) !

One issue I see with this is deciding how to organize tests that are
specific to one version of a module compared to another. For instance,
test_warnings has some tests specific to _warnings because of the
hoops it has to jump through in order to get overriding showwarnings
and friends to work. I guess I could try to make them generic enough
that they don't require a specific module. Otherwise I would insert
the module-specific tests into test_warnings to have that module also
call gnostic_test_warnings to run the universal tests.


More information about the Python-Dev mailing list