dave mankoff
dave mankoff

Reputation: 17779

Python 2.6: proper usage of unittest.TestSuite

Using Python 2.6, I have a very simple test in a python file in a directory:

#mytest.py
import unittest

class BasicTests(unittest.TestCase):
    def test_ok(self):
        self.assertTrue(True)

suite = unittest.TestLoader().loadTestsFromTestCase(BasicTests)

I change into the directory and run python -m unittest mytest.suite and I get the following error:

Traceback (most recent call last):
  File "/usr/lib/python2.6/runpy.py", line 122, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.6/runpy.py", line 34, in _run_code
    exec code in run_globals
  File "/usr/lib/python2.6/unittest.py", line 875, in <module>
    main(module=None)
  File "/usr/lib/python2.6/unittest.py", line 816, in __init__
    self.parseArgs(argv)
  File "/usr/lib/python2.6/unittest.py", line 843, in parseArgs
    self.createTests()
  File "/usr/lib/python2.6/unittest.py", line 849, in createTests
    self.module)
  File "/usr/lib/python2.6/unittest.py", line 613, in loadTestsFromNames
    suites = [self.loadTestsFromName(name, module) for name in names]
  File "/usr/lib/python2.6/unittest.py", line 598, in loadTestsFromName
    test = obj()
  File "/usr/lib/python2.6/unittest.py", line 464, in __call__
    return self.run(*args, **kwds)
TypeError: run() takes exactly 2 arguments (1 given)

I've tried several variations (such as unittest.makeSuite and unittest.LoadTestFromNames) but they all give me the same basic error. What am I missing? I keep reading the documentation and I seem to be following the spec.

Upvotes: 4

Views: 5447

Answers (3)

dave mankoff
dave mankoff

Reputation: 17779

Update: it looks like what I have above is in fact, correct. When I installed a copy of Python 2.7, everything worked fine. I dug through the unittest.py source code and found that this line of code was not working the way one would expect:

    elif isinstance(obj, TestSuite):
        return obj
    elif hasattr(obj, '__call__'):
        test = obj()

The first elif condition is failing, and thus it falls down into the one after where the exception is raised. I'm still not sure how that could even remotely happen — maybe a bad compilation — but I've gone ahead and filed a bug with the provider.

Upvotes: 1

AndiDog
AndiDog

Reputation: 70158

I don't usually work with unittest on the command line, but have my own test running scripts.

You need to add a function suite to the module

def suite():
    return unittest.TestLoader().loadTestsFromTestCase(BasicTests)

and then call it like python -m unittest mytest.suite. But then I run into the following problem:

TypeError: calling <function suite at 0x00C1FB70> returned <unittest.TestSuite tests=[<mysite.BasicTests testMethod=test_ok>]>, not a test

which happens because unittest uses something like isinstance(mytest.suite(), TestSuite) but through executing with -m, you get two different versions of the TestSuite class (one is __main__.TestSuite, the other is unittest.TestSuite), so isinstance returns false.
To me, this looks like a bug. Patching unittest.py by inserting from unittest import TestSuite, TestCase at the beginning of loadTestsFromName solves the isinstance problem. Sorry I can't give you the "correct" solution (if there is one).

Upvotes: 5

unutbu
unutbu

Reputation: 879481

You might want to try:

mytest.py:

import unittest

class BasicTests(unittest.TestCase):
    def test_ok(self):
        self.assertTrue(True)

if __name__ == '__main__':
    unittest.sys.argv.insert(1,'--verbose')
    unittest.main(argv = unittest.sys.argv)    

Then,

% python mytest.py

runs all tests in all subclasses of TestCase, and

% python mytest.py BasicTests.test_ok

runs just test_ok. This second form of the command is useful when you know there is a problem with one test and don't wish to run through every test.

Upvotes: 0

Related Questions