From e60114c716ac78ff3826c68dd8e1f0de1e822015 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Mon, 16 May 2016 07:32:09 -0400 Subject: [PATCH] Add paver arguments to control concurrency and randomization --- docs/en_us/internal/testing.rst | 12 +++++++ pavelib/tests.py | 5 +++ pavelib/utils/test/suites/nose_suite.py | 46 +++++++++++++------------ 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/docs/en_us/internal/testing.rst b/docs/en_us/internal/testing.rst index ec86638db2..a074be9a26 100644 --- a/docs/en_us/internal/testing.rst +++ b/docs/en_us/internal/testing.rst @@ -208,6 +208,18 @@ To run a single test format the command like this. paver test_system -t lms/djangoapps/courseware/tests/tests.py:ActivateLoginTest.test_activate_login +The ``lms`` suite of tests runs concurrently, and with randomized order, by default. +You can override these by using ``--no-randomize`` to disable randomization, +and ``--processes=N`` to control how many tests will run concurrently (``0`` will +disable concurrency). For example: + +:: + # This will run all tests in the order that they appear in their files, serially + paver test_system -s lms --no-randomize --processes=0 + + # This will run using only 2 processes for tests + paver test_system -s lms --processes=2 + To re-run all failing django tests from lms or cms, use the ``--failed``,\ ``-f`` flag (see note at end of section). diff --git a/pavelib/tests.py b/pavelib/tests.py index 61ca58f5f0..e1bde07e39 100644 --- a/pavelib/tests.py +++ b/pavelib/tests.py @@ -31,6 +31,9 @@ __test__ = False # do not collect ('extra_args=', 'e', 'adds as extra args to the test command'), ('cov_args=', 'c', 'adds as args to coverage for the test run'), ('skip_clean', 'C', 'skip cleaning repository before running tests'), + ('processes=', 'p', 'number of processes to use running tests'), + make_option('-r', '--randomize', action='store_true', dest='randomize', help='run the tests in a random order'), + make_option('--no-randomize', action='store_false', dest='randomize', help="don't run the tests in a random order"), make_option("--verbose", action="store_const", const=2, dest="verbosity"), make_option("-q", "--quiet", action="store_const", const=0, dest="verbosity"), make_option("-v", "--verbosity", action="count", dest="verbosity", default=1), @@ -59,6 +62,8 @@ def test_system(options): 'skip_clean': getattr(options, 'skip_clean', False), 'pdb': getattr(options, 'pdb', False), 'disable_migrations': getattr(options, 'disable_migrations', False), + 'processes': getattr(options, 'processes', None), + 'randomize': getattr(options, 'randomize', None), } if test_id: diff --git a/pavelib/utils/test/suites/nose_suite.py b/pavelib/utils/test/suites/nose_suite.py index f5557f6fc5..6243fe5c80 100644 --- a/pavelib/utils/test/suites/nose_suite.py +++ b/pavelib/utils/test/suites/nose_suite.py @@ -113,36 +113,38 @@ class SystemTestSuite(NoseTestSuite): self.test_id = kwargs.get('test_id', self._default_test_id) self.fasttest = kwargs.get('fasttest', False) + self.processes = kwargs.get('processes', None) + self.randomize = kwargs.get('randomize', None) + def __enter__(self): super(SystemTestSuite, self).__enter__() @property def cmd(self): - cmd = ( - './manage.py {system} test --verbosity={verbosity} ' - '{test_id} {test_opts} --settings=test {system_opts} {extra} ' - '--with-xunitmp --xunitmp-file={xunit_report}'.format( - system=self.root, - verbosity=self.verbosity, - test_id=self.test_id, - test_opts=self.test_options_flags, - system_opts=self._system_options, - extra=self.extra_args, - xunit_report=self.report_dir / "nosetests.xml", - ) - ) + if self.processes is None: + # Use one process per core for LMS tests, and no multiprocessing + # otherwise. + self.processes = -1 if self.root == 'lms' else 0 - return self._under_coverage_cmd(cmd) + if self.randomize is None: + self.randomize = self.root == 'lms' - @property - def _system_options(self): - """ - Test arguments that are only enabled for specific systems. - """ - if self.root == 'lms': - return '--with-randomly --with-database-isolation --processes=-1' + cmd = [ + './manage.py', self.root, 'test', + '--verbosity={}'.format(self.verbosity), + self.test_id, + self.test_options_flags, + '--settings=test', + self.extra_args, + '--with-xunitmp', + '--xunitmp-file={}'.format(self.report_dir / "nosetests.xml"), + '--processes={}'.format(self.processes), + '--with-database-isolation', + ] + if self.randomize: + cmd.append('--with-randomly') - return '' + return self._under_coverage_cmd(" ".join(cmd)) @property def _default_test_id(self):