3

I have Python unit test code organized as follows:

Maindir
   |
   |--Dir1
   |  |
   |  |-- test_A.py
   |  |-- test_B.py
   |  |-- test_C.py
   |
   |--Dir2
       | ...

I assume you get the picture. In each of the Dirx directories I have a file named suite.py which puts together a suite of tests from the tests in the give directory (so you can choose specific test, omit other tests, etc.). These files look e.g. like the following (in case to choose all tests, they might also select only a subset of tests) [also consider test <-> unit test]:

import test_A
import test_B
import test_C

suite1 = test.TestSuite()
suite1.addTests(test.TestLoader().loadTestsFromTestCase(test_A.MyTest))
suite1.addTests(test.TestLoader().loadTestsFromTestCase(test_B.MyTest))
suite1.addTests(test.TestLoader().loadTestsFromTestCase(test_C.MyTest))

The main runner, execall.py, in the Maindir directory looks like this:

from Dir1.suite import suite1
from Dir2.suite import suite2

suite_all = test.TestSuite([
    suite1,
    suite2])

if __name__ == '__main__':
    test.main(defaultTest='suite_all')

Now I can do the following:

  • Run all tests: 'execall.py' (as documented)
  • Run a specific suite: execall.py suite1 (as documented)

But how can I run only a specific single test? And how can I run all tests of the specific file? I tried the following without success, with the same error: 'TestSuite' object has no attribute 'xxx'

execall.py suite1.test_A
execall.py suite1.test_A.test1
execall.py test_A
execall.py test_A.test1

execall.py -h gives very specific examples of how to run single tests or tests in testcases, but in my case this does not seem to work.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alex
  • 41,580
  • 88
  • 260
  • 469

1 Answers1

1

One way to do it would be writing your own tests loader. I highly recommend adopting the mechanism found in Flask's testsuite module.

The basic idea is:

  1. Implement a routine which returns a unittest.TestSuite() object with all the Python modules which contain the required tests. This could be done e.g. by scanning the directory for test_XXX.py files (simply checking them by startswith('test'), regexp, etc.).

  2. Subclass unittest.TestLoader and override loadTestsFromName(self, name, module) which would use the testsuite generated in Step1. For example, in Flask:

     for testcase, testname in find_all_tests(suite):
         if testname == name or \
             testname.endswith('.' + name) or \
             ('.' + name + '.') in testname or \
             testname.startswith(name + '.'):
             all_tests.append(testcase)
    

    This allows loading tests by Python module name, by test suite (test class) name or just by test case name.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zaur Nasibov
  • 22,280
  • 12
  • 56
  • 83
  • But this is a larger extension, using a different framework... Too out-of-scope – Alex Dec 07 '12 at 08:26
  • No, this is an open-source, BSD licensed framework, so just take what you need from there. In fact, I used a bit modified Flask's testsuite approach in my own framework. – Zaur Nasibov Dec 07 '12 at 08:40
  • But I seem to require `werkzeug` to get it to work, or not really? – Alex Dec 07 '12 at 08:53
  • Flask does require werkzeug, but I am speaking of using a tiny part of it, a mechanism, and idea, a concept, a way, ... - you name it, of how testing is done in Flask. In the simplest case you'll have to adopt a single `__init__.py` from the testsuite. Reading other programmers code improves one's skills much faster than one can imagine. Armin Ronacher, the author of Flask is a very well known person in the world of Python and learning from his code is a very pleasurable process. – Zaur Nasibov Dec 07 '12 at 08:58