Setuptools has a feature that allows you to run the tests in a distribution by invoking the distribution's "setup.py" script with a "test" argument. As long as the argument's to "setup" within that script contains a "test_suite" parameter which resolves to a module, a package, or a function which returns a unittest TestSuite, it will invoke a unittest TestLoader subclass to find the tests within the distribution; it will then subsquently run them. For instance:
setup(name='news',
...
test_suite = "news",
...
)
The TestLoader subclass that setuptools provides recursively uses the loadTestsFromName method of the unittest TestLoader to find all tests in the package named. Unfortunately, this has two consequences: it catches ImportErrors to guard against bad names found in the path... but if your code itself causes an ImportError, it is swallowed. Additionally, the test loader subclass tries to find all files that end in ".py" in every module. Emacs writes temporary files such as ".#foo.py" that are also found when it is run, which confuses the heck out of the loader. The loader winds up in a place where it just can't cope and throws some sort of ValueError that has no context. At the end of the day, the issue is that the errors that come out of running tests like this are particularly baffling ("Empty module name", and so on).
I tried briefly to sort these issues out. The second issue (the emacs tempfile issue) is easily solved. The first issue is harder; I would have essentially needed to rewrite loadTestsFromNames.
Instead of bothering, I just made my project's tests_require depend
on nose. I then added the following to my package's 'setup.cfg':
[nosetests] match=^test nocapture=1
The first match line in the nosetests section (a regex) matches only
test modules and functions that begin with the literal string test.
This is necessary for my setups because the default regex is more
promiscuous, and finds things like test class base classes. What this
boils down to is that the match=-^test line has the effect of
causing nose to only run unittest.TestCase-derived tests in my
particular setup, due to my own naming conventions. YMMV. The second
line in the nosetests section causes nose to not capture stdout, so I
can use pdb within a test run.
I then adjusted my setup.py setup call to look like so:
setup(name='news',
...
test_suite = "nose.collector",
...
)
When I invoke "setup.py test" now, nose finds and runs the tests and its algorithm for finding tests doesn't choke in the way that the default test loader does on tempfiles and import errors, making it a much nicer experience to debug test failures. It runs the tests in a different order, however (alphabetical by all test names), which is not optimal for my work patterns; I'd prefer it to run each module's test in its declared ordering. But it works. Thanks nose!