[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