python - Passing arguments (for argparse) with unittest discover -


foo python project deep directory nesting, including ~30 unittest files in various subdirectories. within foo's setup.py, i've added custom "test" command internally running

 python -m unittest discover foo '*test.py' 

note uses unittest's discovery mode.


since of tests extremely slow, i've decided tests should have "levels". answer this question explained how unittest , argparse work each other. now, can run individual unittest file, foo/bar/_bar_test.py, with

python foo/bar/_bar_test.py --level=3 

and level-3 tests run.

the problem can't figure out how pass custom flag (in case "--level=3" using discover. try fails, e.g.:

$ python -m unittest discover --level=3 foo '*test.py' usage: python -m unittest discover [options]  python -m unittest discover: error: no such option: --level  $ python -m --level=3 unittest discover foo '*test.py' /usr/bin/python: no module named --level=3 

how can pass --level=3 individual unittests? if possible, i'd avoid dividing different-level tests different files.

bounty edit

the pre-bounty (fine) solution suggests using system environment variables. not bad, i'm looking cleaner.

changing multiple-file test runner (i.e., python -m unittest discover foo '*test.py') else fine, long as:

  1. it allows generating single report multiple-file unittests.
  2. it can somehow support multiple test levels (either using technique in question, or using other different mechanism).

this doesn't pass args using unittest discover, accomplishes trying do.

this leveltest.py. put somewhere in module search path (maybe current directory or site-packages):

import argparse import sys import unittest  # part copied unittest.__main__.py if sys.argv[0].endswith("__main__.py"):     import os.path     # change sys.argv[0] make message more useful     # use executable without path, unquoted     # (it's hint anyway)     # (if have spaces in executable deserve!)     executable = os.path.basename(sys.executable)     sys.argv[0] = executable + " -m leveltest"     del os  def _id(obj):     return obj  # decorator assigns test levels test cases (classes , methods) def level(testlevel):     if unittest.level < testlevel:         return unittest.skip("test level low.")     return _id  def parse_args():     parser = argparse.argumentparser()     parser.add_argument('--level', type=int, default=3)     ns, args = parser.parse_known_args(namespace=unittest)     return ns, sys.argv[:1] + args  if __name__ == "__main__":     ns, remaining_args = parse_args()      # invokes unittest when leveltest invoked -m flag like:     #    python -m leveltest --level=2 discover --verbose     unittest.main(module=none, argv=remaining_args) 

here how use in example testproject.py file:

import unittest import leveltest  # needed before uses of @leveltest.level() decorator #   parse "--level" command argument , set test level when  #   test file run directly -m if __name__ == "__main__":     ns, remaining_args = leveltest.parse_args()  @leveltest.level(2) class teststringmethods(unittest.testcase):      @leveltest.level(5)     def test_upper(self):         self.assertequal('foo'.upper(), 'foo')      @leveltest.level(3)     def test_isupper(self):         self.asserttrue('foo'.isupper())         self.assertfalse('foo'.isupper())      @leveltest.level(4)     def test_split(self):         s = 'hello world'         self.assertequal(s.split(), ['hello', 'world'])         # check s.split fails when separator not string         self.assertraises(typeerror):             s.split(2)  if __name__ == '__main__':     # invokes unittest when file executed -m     unittest.main(argv=remaining_args) 

you can run tests running testproject.py directly, like:

~roottwo\projects> python testproject.py --level 2 -v test_isupper (__main__.teststringmethods) ... skipped 'test level low.' test_split (__main__.teststringmethods) ... skipped 'test level low.' test_upper (__main__.teststringmethods) ... skipped 'test level low.'  ---------------------------------------------------------------------- ran 3 tests in 0.000s  ok (skipped=3)  ~roottwo\projects> python testproject.py --level 3 -v test_isupper (__main__.teststringmethods) ... ok test_split (__main__.teststringmethods) ... skipped 'test level low.' test_upper (__main__.teststringmethods) ... skipped 'test level low.'  ---------------------------------------------------------------------- ran 3 tests in 0.001s  ok (skipped=2)  ~roottwo\projects> python testproject.py --level 4 -v test_isupper (__main__.teststringmethods) ... ok test_split (__main__.teststringmethods) ... ok test_upper (__main__.teststringmethods) ... skipped 'test level low.'  ---------------------------------------------------------------------- ran 3 tests in 0.001s  ok (skipped=1)  ~roottwo\projects> python testproject.py --level 5 -v test_isupper (__main__.teststringmethods) ... ok test_split (__main__.teststringmethods) ... ok test_upper (__main__.teststringmethods) ... ok  ---------------------------------------------------------------------- ran 3 tests in 0.001s  ok 

by using unittest discovery this:

~roottwo\projects> python -m leveltest --level 2 -v test_isupper (testproject.teststringmethods) ... skipped 'test level low.' test_split (testproject.teststringmethods) ... skipped 'test level low.' test_upper (testproject.teststringmethods) ... skipped 'test level low.'  ---------------------------------------------------------------------- ran 3 tests in 0.003s  ok (skipped=3)  ~roottwo\projects> python -m leveltest --level 3 discover -v test_isupper (testproject.teststringmethods) ... ok test_split (testproject.teststringmethods) ... skipped 'test level low.' test_upper (testproject.teststringmethods) ... skipped 'test level low.'  ---------------------------------------------------------------------- ran 3 tests in 0.001s  ok (skipped=2)  ~roottwo\projects> python -m leveltest --level 4 -v test_isupper (testproject.teststringmethods) ... ok test_split (testproject.teststringmethods) ... ok test_upper (testproject.teststringmethods) ... skipped 'test level low.'  ---------------------------------------------------------------------- ran 3 tests in 0.001s  ok (skipped=1)  ~roottwo\projects> python -m leveltest discover --level 5 -v test_isupper (testproject.teststringmethods) ... ok test_split (testproject.teststringmethods) ... ok test_upper (testproject.teststringmethods) ... ok  ---------------------------------------------------------------------- ran 3 tests in 0.001s  ok 

or specifying test cases run, like:

~roottwo\projects>python -m leveltest --level 3 testproject -v test_isupper (testproject.teststringmethods) ... ok test_split (testproject.teststringmethods) ... skipped 'test level low.' test_upper (testproject.teststringmethods) ... skipped 'test level low.'  ---------------------------------------------------------------------- ran 3 tests in 0.002s  ok (skipped=2) 

Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -