[TIP] Test discovery for unittest
Olemis Lang
olemis at gmail.com
Fri Apr 10 10:06:31 PDT 2009
On Fri, Apr 10, 2009 at 11:28 AM, Michael Foord
<fuzzyman at voidspace.org.uk> wrote:
> Olemis Lang wrote:
>>
>> [snip...]
>>>
>>> I am considering your point that this functionality better belongs
>>> in a loader than a suite though.
>>
>> In that point ... how different would it be from PackageTestLoader ?
>
> unittest has no PackageTestLoader. I assume you mean one in dutest? Perhaps
> you can tell us how it is different.
>
I already provided URL so that u all could see it. Therefore I include
it here. Just for the record :
{{{
class PackageTestLoader(unittest.TestLoader):
"""A unittest-like loader (Decorator/Wrapper class) that recursively
retrieves all the tests included in all the modules found within a
specified package and the hierarchy it determines. Some filters
(i.e. regex) may be specified to limit the modules contributing to
the resulting test suite."""
defaultPattern = re.compile(".*")
def __init__(self, pattern=defaultPattern, loader=defaultTestLoader,
impall=False, globs={}, ns={},
):
"""Initializes this test loader. Parameters have the following
meaning :
param pattern: A regular expression object (see re module)
used to filter the modules which will be inspected so as
to retrieve the test suite. If not specified then all
modules will be processed looking for tests.
param loader: Specify the loader used to retrieve test cases
from each (single) module matching the aforementioned
criteria.
param impall: If the value of this flag evaluates to true then
all the modules inside the package hierarchy will be
imported (disregarding whether they will contribute to the
test suite or not). Otherwise only those packages for
which a match is made (i.e. those contributing to the test
suite) are imported directly.
param globs: The global namespace in which module imports will
be carried out.
param ns: The local namespace in which module imports will
be carried out.
"""
super(PackageTestLoader, self).__init__()
self.pattern = pattern
self.loader = loader
self.impall = impall
self.locals = ns
self.globs = globs
def loadTestsFromTestCase(self, testCaseClass):
"""Return a suite of all tests cases contained in
testCaseClass as determined by the wrapped test loader.
"""
return self.loader.loadTestsFromTestCase(testCaseClass)
def loadTestsFromModule(self, module):
"""Return a suite of all test cases contained in the given
package and the modules it contains recursively.
If a ``pattern`` was not specified to the initializer then all
modules (packages) in the aformentioned hierarchy are
considered. Otherwise a test suite is retrieved for all those
modules having a name matching this pattern. They are packed
together into another test suite (its type being standard
self.suiteClass) which is returned to the caller.
If the attribute ``impall`` is set, then all modules in the
former hierarchy are imported disregarding whether they will
be inspected when looking for tests or not.
"""
if os.path.basename(module.__file__) != '__init__.pyc':
return self.loader.loadTestsFromModule(module)
else:
loader = self.loader
root_dir = os.path.dirname(module.__file__)
pkg_name = module.__name__
idx = len(pkg_name)
pend_names = [module.__name__]
suite = self.suiteClass()
if self.pattern.match(module.__name__) is not None:
suite.addTest(loader.loadTestsFromModule(module))
for modnm in pend_names:
curdir = root_dir + modnm[idx:].replace('.', os.sep)
for fname in os.listdir(curdir):
ch_path = os.path.join(curdir, fname)
if os.path.isdir(ch_path) \
and os.path.exists(os.path.join(ch_path,
'__init__.py')):
child_name = '.'.join([modnm, fname])
pend_names.append(child_name)
elif fname.endswith('.py') and \
fname != '__init__.py':
child_name = '.'.join([modnm, fname[:-3]])
else:
continue
if self.pattern.match(child_name) is not None:
__import__(child_name, self.globs,
self.locals, [], -1)
suite.addTest(loader.loadTestsFromModule(
modules[child_name]))
elif self.impall:
__import__(child_name, self.globs,
self.locals, [], -1)
return suite
}}}
> You snipped out without answering my question about how DiscoveringTestSuite
> inhibits reusability - an assertion (no pun intended) you made in your
> previous email.
Later ... now I'm employing some bullets to kill these annoying mosquitos :)
>>> I'm sure there are many good things in dutest. Integration of doctest and
>>> unittest is something worth looking at in the future but is not something
>>> I
>>> have bandwidth for at the moment.
>>
>> [...]
>>
>>> (Particularly as I *personally* feel that
>>> docttest is a horrible unit testing tool - but excellent for testing
>>> examples in documentation.)
>>
>> I personally think that doctest is the most beautiful implementation
>> ever made for the following XUnit test patterns :
>>
>> - Deltha Assertion
>> - Scripted Test
>> - Recorded Test
>> - Data-Driven Test
>> - Behavior Verification
>> - State Verification
>>
>> and still allows being meta + agile
>
> Doctest is simply awful for Test Driven Development, the cornerstone of
> agile.
>
Ok ... perhaps others like vanilla (doctest) others chocolate
(unittest) and I just prefer the mixin (dutest), while others maybe
like other flavours (nose, py.test, ...) and so on ...
--
Regards,
Olemis.
Blog ES: http://simelo-es.blogspot.com/
Blog EN: http://simelo-en.blogspot.com/
Featured article:
Se retira el BDFL ... ¿El fin de Python 3k? -
http://feedproxy.google.com/~r/simelo-es/~3/HpncxTKfB1c/se-retira-el-bdfl-el-fin-de-python-3k_02.html
More information about the testing-in-python
mailing list