summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2012-12-19 16:37:47 +1300
committerRobert Collins <robertc@robertcollins.net>2012-12-19 16:37:47 +1300
commit41939b95d254e75ef4e7a5525e4742c7e599499e (patch)
tree3f1a06e51e1bf7d86ab9f6a84a6c96efe1383cad
parentb4fdb43317ad5611ea3816e94a5c9b1cc838f762 (diff)
downloadtestrepository-41939b95d254e75ef4e7a5525e4742c7e599499e.tar.gz
* It's now possible to configure ``test_run_concurrency`` in ``.testr.conf``
to have concurrency defined by a callout. (Robert Collins)
-rw-r--r--NEWS6
-rw-r--r--testrepository/testcommand.py18
-rw-r--r--testrepository/tests/test_testcommand.py42
3 files changed, 62 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index 74f56e6..7c1bf86 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,12 @@ testrepository release notes
NEXT (In development)
+++++++++++++++++++++
+IMPROVEMENTS
+------------
+
+* It's now possible to configure ``test_run_concurrency`` in ``.testr.conf``
+ to have concurrency defined by a callout. (Robert Collins)
+
0.0.9
+++++
diff --git a/testrepository/testcommand.py b/testrepository/testcommand.py
index 84fcf4c..eb06302 100644
--- a/testrepository/testcommand.py
+++ b/testrepository/testcommand.py
@@ -147,6 +147,8 @@ class TestListingFixture(Fixture):
else:
self.concurrency = self.ui.options.concurrency
if not self.concurrency:
+ self.concurrency = self.callout_concurrency()
+ if not self.concurrency:
self.concurrency = self.local_concurrency()
if not self.concurrency:
self.concurrency = 1
@@ -286,6 +288,22 @@ class TestListingFixture(Fixture):
partition.append(test_id)
return partitions
+ def callout_concurrency(self):
+ """Callout for user defined concurrency."""
+ try:
+ concurrency_cmd = self._parser.get(
+ 'DEFAULT', 'test_run_concurrency', None)
+ except ConfigParser.NoOptionError:
+ return None
+ run_proc = self.ui.subprocess_Popen(concurrency_cmd, shell=True,
+ stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+ out, err = run_proc.communicate()
+ if run_proc.returncode:
+ raise ValueError(
+ "test_run_concurrency failed: exit code %d, stderr=%r" % (
+ run_proc.returncode, err))
+ return int(out.strip())
+
def local_concurrency(self):
if sys.platform == 'linux2':
concurrency = None
diff --git a/testrepository/tests/test_testcommand.py b/testrepository/tests/test_testcommand.py
index 2b66997..ecdc012 100644
--- a/testrepository/tests/test_testcommand.py
+++ b/testrepository/tests/test_testcommand.py
@@ -18,7 +18,7 @@ import os.path
import optparse
import re
-from testtools.matchers import MatchesException, Raises
+from testtools.matchers import MatchesException, raises
from testtools.testresult.doubles import ExtendedTestResult
from testrepository.commands import run
@@ -78,14 +78,14 @@ class TestTestCommand(ResourcedTestCase):
def test_get_run_command_no_config_file_errors(self):
ui, command = self.get_test_ui_and_cmd()
self.assertThat(command.get_run_command,
- Raises(MatchesException(ValueError('No .testr.conf config file'))))
+ raises(ValueError('No .testr.conf config file')))
def test_get_run_command_no_config_settings_errors(self):
ui, command = self.get_test_ui_and_cmd()
self.set_config('')
self.assertThat(command.get_run_command,
- Raises(MatchesException(ValueError(
- 'No test_command option present in .testr.conf'))))
+ raises(ValueError(
+ 'No test_command option present in .testr.conf')))
def test_get_run_command_returns_fixture_makes_IDFILE(self):
ui, command = self.get_test_ui_and_cmd()
@@ -244,6 +244,40 @@ class TestTestCommand(ResourcedTestCase):
self.set_config('[DEFAULT]\nfilter_tags=foo bar\n')
self.assertEqual(set(['foo', 'bar']), command.get_filter_tags())
+ def test_callout_concurrency(self):
+ ui, command = self.get_test_ui_and_cmd()
+ ui.proc_outputs = ['4']
+ self.set_config(
+ '[DEFAULT]\ntest_run_concurrency=probe\n'
+ 'test_command=foo\n')
+ fixture = self.useFixture(command.get_run_command())
+ self.assertEqual(4, fixture.callout_concurrency())
+ self.assertEqual([
+ ('popen', ('probe',), {'shell': True, 'stdin': -1, 'stdout': -1}),
+ ('communicate',)], ui.outputs)
+
+ def test_callout_concurrency_failed(self):
+ ui, command = self.get_test_ui_and_cmd()
+ ui.proc_results = [1]
+ self.set_config(
+ '[DEFAULT]\ntest_run_concurrency=probe\n'
+ 'test_command=foo\n')
+ fixture = self.useFixture(command.get_run_command())
+ self.assertThat(lambda:fixture.callout_concurrency(), raises(
+ ValueError("test_run_concurrency failed: exit code 1, stderr=''")))
+ self.assertEqual([
+ ('popen', ('probe',), {'shell': True, 'stdin': -1, 'stdout': -1}),
+ ('communicate',)], ui.outputs)
+
+ def test_callout_concurrency_not_set(self):
+ ui, command = self.get_test_ui_and_cmd()
+ self.set_config(
+ '[DEFAULT]\n'
+ 'test_command=foo\n')
+ fixture = self.useFixture(command.get_run_command())
+ self.assertEqual(None, fixture.callout_concurrency())
+ self.assertEqual([], ui.outputs)
+
def test_make_result(self):
# Just a simple 'the dots are joined' test. More later.
ui, command = self.get_test_ui_and_cmd()