I have a project that has almost complete unit test coverage. There's only one statement that isn't covered and I can't work out a good way to do so. Say the project is called foo, I have foo/commands.py:
#!/usr/bin/python [...] def main(argv): [...] if __name__ == '__main__': return main(sys.argv) # This line allegedly not covered by tests
I do have a test for it! foo/tests/test_commands.py:
import unittest class CommandsTest(unittest.TestCase): def test_direct_call(self): proc = subprocess.Popen(['python', 'foo/commands.py', 'help'], stdout=PIPE) stdout, stderr = proc.communicate() self.assertTrue(stdout.startswith('usage:')) self.assertEquals(0, proc.returncode)
(That's not my actual test, but it's along those lines.)
I use nose as my test runner:
nosetests --cover-erase --cover-tests --with-coverage --cover-package=foo -vs foo
The problem is that this particular statement isn't considered "covered", because I use plain python instead of coverage.py (or python-coverage as its called on Ubuntu). I could change it to python-coverage, but I don't really want to do that:
- It may not be available.
- If it is available, it may be named differently.
- It's ok if someone wants to run the test suite without the coverage stuff.
Right now, I have a dreadful hack to do it:
interpreter = 'coverage' in sys.modules ['python-coverage', 'run'] or ['python']
Not exactly the most readable code, but imagine the irony of using the more readable approach:
if 'coverage' in sys.modules: interpreter = ['python-coverage', 'run'] else: interpreter = ['python']
...only to realise that the "else:" branch ends up not getting called when coverage is enabled, so I just have another line of code that's not exercised by unit tests.
My goal is to fail the test suite if there isn't 100% coverage. I "need" the statement in foo/commands.py because it's a very convenient way to test things during development (in actual installs, it'll use distutils console_scripts magic to call into this file).
Ideas? Prior art? Anything?
Note: 100% coverage is by no means a guarantee that everything is great. Less than 100% is a guarantee, though, that there's something you're not testing. I can easily verify the 100% coverage, so I see no reason not to.