Commit 6b61bc44 by Calen Pennington

Covert all paver command manipulation to happen on lists of args/options, rather than strings

parent ef89c75b
...@@ -137,7 +137,7 @@ class TestPaverJavaScriptTestTasks(PaverTestCase): ...@@ -137,7 +137,7 @@ class TestPaverJavaScriptTestTasks(PaverTestCase):
suite=suite suite=suite
) )
if port: if port:
expected_test_tool_command += u" --port {port}".format(port=port) expected_test_tool_command += u" --port={port}".format(port=port)
expected_messages.append(expected_test_tool_command) expected_messages.append(expected_test_tool_command)
self.assertEquals(self.task_messages, expected_messages) self.assertEquals(self.task_messages, expected_messages)
...@@ -24,25 +24,24 @@ class TestPaverBokChoyCmd(unittest.TestCase): ...@@ -24,25 +24,24 @@ class TestPaverBokChoyCmd(unittest.TestCase):
and store. and store.
""" """
expected_statement = ( shard_str = '/shard_' + self.shard if self.shard else ''
"DEFAULT_STORE={default_store} "
"SCREENSHOT_DIR='{repo_dir}/test_root/log{shard_str}' " expected_statement = [
"BOK_CHOY_HAR_DIR='{repo_dir}/test_root/log{shard_str}/hars' " "DEFAULT_STORE={}".format(store),
"BOKCHOY_A11Y_CUSTOM_RULES_FILE='{repo_dir}/{a11y_custom_file}' " "SCREENSHOT_DIR='{}/test_root/log{}'".format(REPO_DIR, shard_str),
"SELENIUM_DRIVER_LOG_DIR='{repo_dir}/test_root/log{shard_str}' " "BOK_CHOY_HAR_DIR='{}/test_root/log{}/hars'".format(REPO_DIR, shard_str),
"VERIFY_XSS='{verify_xss}' " "BOKCHOY_A11Y_CUSTOM_RULES_FILE='{}/{}'".format(
"nosetests {repo_dir}/common/test/acceptance/{exp_text} " REPO_DIR,
"--with-xunit " 'node_modules/edx-custom-a11y-rules/lib/custom_a11y_rules.js'
"--xunit-file={repo_dir}/reports/bok_choy{shard_str}/xunit.xml " ),
"--verbosity=2 " "SELENIUM_DRIVER_LOG_DIR='{}/test_root/log{}'".format(REPO_DIR, shard_str),
).format( "VERIFY_XSS='{}'".format(verify_xss),
default_store=store, "nosetests",
repo_dir=REPO_DIR, "{}/common/test/acceptance/{}".format(REPO_DIR, name),
shard_str='/shard_' + self.shard if self.shard else '', "--with-xunit",
exp_text=name, "--xunit-file={}/reports/bok_choy{}/xunit.xml".format(REPO_DIR, shard_str),
a11y_custom_file='node_modules/edx-custom-a11y-rules/lib/custom_a11y_rules.js', "--verbosity=2",
verify_xss=verify_xss ]
)
return expected_statement return expected_statement
def setUp(self): def setUp(self):
...@@ -93,7 +92,7 @@ class TestPaverBokChoyCmd(unittest.TestCase): ...@@ -93,7 +92,7 @@ class TestPaverBokChoyCmd(unittest.TestCase):
def test_serversonly(self): def test_serversonly(self):
suite = BokChoyTestSuite('', serversonly=True) suite = BokChoyTestSuite('', serversonly=True)
self.assertEqual(suite.cmd, "") self.assertEqual(suite.cmd, None)
def test_verify_xss(self): def test_verify_xss(self):
suite = BokChoyTestSuite('', verify_xss=True) suite = BokChoyTestSuite('', verify_xss=True)
...@@ -119,14 +118,16 @@ class TestPaverBokChoyCmd(unittest.TestCase): ...@@ -119,14 +118,16 @@ class TestPaverBokChoyCmd(unittest.TestCase):
""" """
Using 1 process means paver should ask for the traditional xunit plugin for plugin results Using 1 process means paver should ask for the traditional xunit plugin for plugin results
""" """
expected_verbosity_string = ( expected_verbosity_command = [
"--with-xunit --xunit-file={repo_dir}/reports/bok_choy{shard_str}/xunit.xml --verbosity=2".format( "--with-xunit",
"--xunit-file={repo_dir}/reports/bok_choy{shard_str}/xunit.xml".format(
repo_dir=REPO_DIR, repo_dir=REPO_DIR,
shard_str='/shard_' + self.shard if self.shard else '' shard_str='/shard_' + self.shard if self.shard else ''
) ),
) "--verbosity=2",
]
suite = BokChoyTestSuite('', num_processes=1) suite = BokChoyTestSuite('', num_processes=1)
self.assertEqual(BokChoyTestSuite.verbosity_processes_string(suite), expected_verbosity_string) self.assertEqual(suite.verbosity_processes_command, expected_verbosity_command)
def test_verbosity_settings_2_processes(self): def test_verbosity_settings_2_processes(self):
""" """
...@@ -134,32 +135,36 @@ class TestPaverBokChoyCmd(unittest.TestCase): ...@@ -134,32 +135,36 @@ class TestPaverBokChoyCmd(unittest.TestCase):
be used. be used.
""" """
process_count = 2 process_count = 2
expected_verbosity_string = ( expected_verbosity_command = [
"--with-xunitmp --xunitmp-file={repo_dir}/reports/bok_choy{shard_str}/xunit.xml" "--with-xunitmp",
" --processes={procs} --no-color --process-timeout=1200".format( "--xunitmp-file={repo_dir}/reports/bok_choy{shard_str}/xunit.xml".format(
repo_dir=REPO_DIR, repo_dir=REPO_DIR,
shard_str='/shard_' + self.shard if self.shard else '', shard_str='/shard_' + self.shard if self.shard else '',
procs=process_count ),
) "--processes={}".format(process_count),
) "--no-color",
"--process-timeout=1200",
]
suite = BokChoyTestSuite('', num_processes=process_count) suite = BokChoyTestSuite('', num_processes=process_count)
self.assertEqual(BokChoyTestSuite.verbosity_processes_string(suite), expected_verbosity_string) self.assertEqual(suite.verbosity_processes_command, expected_verbosity_command)
def test_verbosity_settings_3_processes(self): def test_verbosity_settings_3_processes(self):
""" """
With the above test, validate that num_processes can be set to various values With the above test, validate that num_processes can be set to various values
""" """
process_count = 3 process_count = 3
expected_verbosity_string = ( expected_verbosity_command = [
"--with-xunitmp --xunitmp-file={repo_dir}/reports/bok_choy{shard_str}/xunit.xml" "--with-xunitmp",
" --processes={procs} --no-color --process-timeout=1200".format( "--xunitmp-file={repo_dir}/reports/bok_choy{shard_str}/xunit.xml".format(
repo_dir=REPO_DIR, repo_dir=REPO_DIR,
shard_str='/shard_' + self.shard if self.shard else '', shard_str='/shard_' + self.shard if self.shard else '',
procs=process_count ),
) "--processes={}".format(process_count),
) "--no-color",
"--process-timeout=1200",
]
suite = BokChoyTestSuite('', num_processes=process_count) suite = BokChoyTestSuite('', num_processes=process_count)
self.assertEqual(BokChoyTestSuite.verbosity_processes_string(suite), expected_verbosity_string) self.assertEqual(suite.verbosity_processes_command, expected_verbosity_command)
def test_invalid_verbosity_and_processes(self): def test_invalid_verbosity_and_processes(self):
""" """
...@@ -168,7 +173,8 @@ class TestPaverBokChoyCmd(unittest.TestCase): ...@@ -168,7 +173,8 @@ class TestPaverBokChoyCmd(unittest.TestCase):
""" """
suite = BokChoyTestSuite('', num_processes=2, verbosity=3) suite = BokChoyTestSuite('', num_processes=2, verbosity=3)
with self.assertRaises(BuildFailure): with self.assertRaises(BuildFailure):
BokChoyTestSuite.verbosity_processes_string(suite) # pylint: disable=pointless-statement
suite.verbosity_processes_command
class TestPaverPa11yCrawlerCmd(unittest.TestCase): class TestPaverPa11yCrawlerCmd(unittest.TestCase):
...@@ -192,17 +198,16 @@ class TestPaverPa11yCrawlerCmd(unittest.TestCase): ...@@ -192,17 +198,16 @@ class TestPaverPa11yCrawlerCmd(unittest.TestCase):
""" """
Returns the expected command to run pa11ycrawler. Returns the expected command to run pa11ycrawler.
""" """
expected_statement = ( expected_statement = [
'pa11ycrawler run {start_urls} ' 'pa11ycrawler',
'--pa11ycrawler-allowed-domains=localhost ' 'run',
'--pa11ycrawler-reports-dir={report_dir} ' ] + start_urls + [
'--pa11ycrawler-deny-url-matcher=logout ' '--pa11ycrawler-allowed-domains=localhost',
'--pa11y-reporter="1.0-json" ' '--pa11ycrawler-reports-dir={}'.format(report_dir),
'--depth-limit=6 ' '--pa11ycrawler-deny-url-matcher=logout',
).format( '--pa11y-reporter="1.0-json"',
start_urls=' '.join(start_urls), '--depth-limit=6',
report_dir=report_dir, ]
)
return expected_statement return expected_statement
def test_default(self): def test_default(self):
......
...@@ -34,22 +34,21 @@ class AcceptanceTest(TestSuite): ...@@ -34,22 +34,21 @@ class AcceptanceTest(TestSuite):
def cmd(self): def cmd(self):
report_file = self.report_dir / "{}.xml".format(self.system) report_file = self.report_dir / "{}.xml".format(self.system)
report_args = "--with-xunit --xunit-file {}".format(report_file) report_args = ["--with-xunit", "--xunit-file {}".format(report_file)]
cmd = ( return [
"DEFAULT_STORE={default_store} ./manage.py {system} --settings acceptance harvest --traceback " "DEFAULT_STORE={}".format(self.default_store),
"--debug-mode --verbosity {verbosity} {pdb}{report_args} {extra_args} {passthrough}".format( "./manage.py",
default_store=self.default_store, self.system,
system=self.system, "--settings=acceptance",
verbosity=self.verbosity, "harvest",
pdb="--pdb " if self.pdb else "", "--traceback",
report_args=report_args, "--debug-mode",
extra_args=self.extra_args, "--verbosity={}".format(self.verbosity),
passthrough=self.passthrough_options "--pdb" if self.pdb else "",
) ] + report_args + [
) self.extra_args
] + self.passthrough_options
return cmd
def _update_assets(self): def _update_assets(self):
""" """
......
...@@ -118,33 +118,36 @@ class BokChoyTestSuite(TestSuite): ...@@ -118,33 +118,36 @@ class BokChoyTestSuite(TestSuite):
sh("./manage.py lms --settings bok_choy flush --traceback --noinput") sh("./manage.py lms --settings bok_choy flush --traceback --noinput")
bokchoy_utils.clear_mongo() bokchoy_utils.clear_mongo()
def verbosity_processes_string(self): @property
def verbosity_processes_command(self):
""" """
Multiprocessing, xunit, color, and verbosity do not work well together. We need to construct Multiprocessing, xunit, color, and verbosity do not work well together. We need to construct
the proper combination for use with nosetests. the proper combination for use with nosetests.
""" """
substring = [] command = []
if self.verbosity != DEFAULT_VERBOSITY and self.num_processes != DEFAULT_NUM_PROCESSES: if self.verbosity != DEFAULT_VERBOSITY and self.num_processes != DEFAULT_NUM_PROCESSES:
msg = 'Cannot pass in both num_processors and verbosity. Quitting' msg = 'Cannot pass in both num_processors and verbosity. Quitting'
raise BuildFailure(msg) raise BuildFailure(msg)
if self.num_processes != 1: if self.num_processes != 1:
# Construct "multiprocess" nosetest substring # Construct "multiprocess" nosetest command
substring = [ command = [
"--with-xunitmp --xunitmp-file={}".format(self.xunit_report), "--with-xunitmp",
"--xunitmp-file={}".format(self.xunit_report),
"--processes={}".format(self.num_processes), "--processes={}".format(self.num_processes),
"--no-color --process-timeout=1200" "--no-color",
"--process-timeout=1200",
] ]
else: else:
substring = [ command = [
"--with-xunit", "--with-xunit",
"--xunit-file={}".format(self.xunit_report), "--xunit-file={}".format(self.xunit_report),
"--verbosity={}".format(self.verbosity), "--verbosity={}".format(self.verbosity),
] ]
return " ".join(substring) return command
def prepare_bokchoy_run(self): def prepare_bokchoy_run(self):
""" """
...@@ -224,7 +227,7 @@ class BokChoyTestSuite(TestSuite): ...@@ -224,7 +227,7 @@ class BokChoyTestSuite(TestSuite):
def cmd(self): def cmd(self):
""" """
This method composes the nosetests command to send to the terminal. If nosetests aren't being run, This method composes the nosetests command to send to the terminal. If nosetests aren't being run,
the command returns an empty string. the command returns None.
""" """
# Default to running all tests if no specific test is specified # Default to running all tests if no specific test is specified
if not self.test_spec: if not self.test_spec:
...@@ -235,7 +238,7 @@ class BokChoyTestSuite(TestSuite): ...@@ -235,7 +238,7 @@ class BokChoyTestSuite(TestSuite):
# Skip any additional commands (such as nosetests) if running in # Skip any additional commands (such as nosetests) if running in
# servers only mode # servers only mode
if self.serversonly: if self.serversonly:
return "" return None
# Construct the nosetests command, specifying where to save # Construct the nosetests command, specifying where to save
# screenshots and XUnit XML reports # screenshots and XUnit XML reports
...@@ -248,16 +251,15 @@ class BokChoyTestSuite(TestSuite): ...@@ -248,16 +251,15 @@ class BokChoyTestSuite(TestSuite):
"VERIFY_XSS='{}'".format(self.verify_xss), "VERIFY_XSS='{}'".format(self.verify_xss),
"nosetests", "nosetests",
test_spec, test_spec,
"{}".format(self.verbosity_processes_string()) ] + self.verbosity_processes_command
]
if self.pdb: if self.pdb:
cmd.append("--pdb") cmd.append("--pdb")
if self.save_screenshots: if self.save_screenshots:
cmd.append("--with-save-baseline") cmd.append("--with-save-baseline")
cmd.append(self.extra_args) if self.extra_args:
cmd.append(self.extra_args)
cmd.extend(self.passthrough_options) cmd.extend(self.passthrough_options)
cmd = (" ").join(cmd)
return cmd return cmd
...@@ -353,19 +355,14 @@ class Pa11yCrawler(BokChoyTestSuite): ...@@ -353,19 +355,14 @@ class Pa11yCrawler(BokChoyTestSuite):
""" """
Runs pa11ycrawler as staff user against the test course. Runs pa11ycrawler as staff user against the test course.
""" """
cmd_str = ( cmd = [
'pa11ycrawler run {start_urls} ' 'pa11ycrawler',
'--pa11ycrawler-allowed-domains={allowed_domains} ' 'run',
'--pa11ycrawler-reports-dir={report_dir} ' ] + self.start_urls + [
'--pa11ycrawler-deny-url-matcher={dont_go_here} ' '--pa11ycrawler-allowed-domains=localhost',
'--pa11y-reporter="{reporter}" ' '--pa11ycrawler-reports-dir={}'.format(self.pa11y_report_dir),
'--depth-limit={depth} ' '--pa11ycrawler-deny-url-matcher=logout',
).format( '--pa11y-reporter="1.0-json"',
start_urls=' '.join(self.start_urls), '--depth-limit=6',
allowed_domains='localhost', ]
report_dir=self.pa11y_report_dir, return cmd
reporter="1.0-json",
dont_go_here="logout",
depth="6",
)
return cmd_str
...@@ -76,21 +76,22 @@ class JsTestSubSuite(TestSuite): ...@@ -76,21 +76,22 @@ class JsTestSubSuite(TestSuite):
""" """
Run the tests using karma runner. Run the tests using karma runner.
""" """
cmd = ( cmd = [
"karma start {test_conf_file} --single-run={single_run} --capture-timeout=60000 " "karma",
"--junitreportpath={xunit_report}".format( "start",
single_run='false' if self.mode == 'dev' else 'true', self.test_conf_file,
test_conf_file=self.test_conf_file, "--single-run={}".format('false' if self.mode == 'dev' else 'true'),
xunit_report=self.xunit_report, "--capture-timeout=60000",
) "--junitreportpath={}".format(self.xunit_report),
) ]
if self.port: if self.port:
cmd += " --port {port}".format(port=self.port) cmd.append("--port={}".format(self.port))
if self.run_under_coverage: if self.run_under_coverage:
cmd += " --coverage --coveragereportpath={report_path}".format( cmd.extend([
report_path=self.coverage_report "--coverage",
) "--coveragereportpath={}".format(self.coverage_report),
])
return cmd return cmd
...@@ -59,23 +59,21 @@ class NoseTestSuite(TestSuite): ...@@ -59,23 +59,21 @@ class NoseTestSuite(TestSuite):
unaltered otherwise. unaltered otherwise.
""" """
if self.run_under_coverage: if self.run_under_coverage:
cmd0, cmd_rest = cmd.split(" ", 1)
# We use "python -m coverage" so that the proper python # We use "python -m coverage" so that the proper python
# will run the importable coverage rather than the # will run the importable coverage rather than the
# coverage that OS path finds. # coverage that OS path finds.
if not cmd0.endswith('.py'): if not cmd[0].endswith('.py'):
cmd0 = "`which {}`".format(cmd0) cmd[0] = "`which {}`".format(cmd[0])
cmd = ( cmd = [
"python -m coverage run {cov_args} --rcfile={rcfile} " "python",
"{cmd0} {cmd_rest}".format( "-m",
cov_args=self.cov_args, "coverage",
rcfile=Env.PYTHON_COVERAGERC, "run",
cmd0=cmd0, self.cov_args,
cmd_rest=cmd_rest, "--rcfile={}".format(Env.PYTHON_COVERAGERC),
) ] + cmd
)
return cmd return cmd
...@@ -85,14 +83,14 @@ class NoseTestSuite(TestSuite): ...@@ -85,14 +83,14 @@ class NoseTestSuite(TestSuite):
Takes the test options and returns the appropriate flags Takes the test options and returns the appropriate flags
for the command. for the command.
""" """
opts = " " opts = []
# Handle "--failed" as a special case: we want to re-run only # Handle "--failed" as a special case: we want to re-run only
# the tests that failed within our Django apps # the tests that failed within our Django apps
# This sets the --failed flag for the nosetests command, so this # This sets the --failed flag for the nosetests command, so this
# functionality is the same as described in the nose documentation # functionality is the same as described in the nose documentation
if self.failed_only: if self.failed_only:
opts += "--failed" opts.append("--failed")
# This makes it so we use nose's fail-fast feature in two cases. # This makes it so we use nose's fail-fast feature in two cases.
# Case 1: --fail-fast is passed as an arg in the paver command # Case 1: --fail-fast is passed as an arg in the paver command
...@@ -102,13 +100,13 @@ class NoseTestSuite(TestSuite): ...@@ -102,13 +100,13 @@ class NoseTestSuite(TestSuite):
) )
if self.fail_fast or env_fail_fast_set: if self.fail_fast or env_fail_fast_set:
opts += " --stop" opts.append("--stop")
if self.pdb: if self.pdb:
opts += " --pdb" opts += " --pdb"
if self.use_ids: if self.use_ids:
opts += " --with-id" opts.append("--with-id")
return opts return opts
...@@ -152,7 +150,7 @@ class SystemTestSuite(NoseTestSuite): ...@@ -152,7 +150,7 @@ class SystemTestSuite(NoseTestSuite):
'./manage.py', self.root, 'test', './manage.py', self.root, 'test',
'--verbosity={}'.format(self.verbosity), '--verbosity={}'.format(self.verbosity),
self.test_id, self.test_id,
self.test_options_flags, ] + self.test_options_flags + [
'--settings=test', '--settings=test',
self.extra_args, self.extra_args,
'--with-xunitmp', '--with-xunitmp',
...@@ -168,7 +166,7 @@ class SystemTestSuite(NoseTestSuite): ...@@ -168,7 +166,7 @@ class SystemTestSuite(NoseTestSuite):
cmd.extend(self.passthrough_options) cmd.extend(self.passthrough_options)
return self._under_coverage_cmd(" ".join(cmd)) return self._under_coverage_cmd(cmd)
@property @property
def _default_test_id(self): def _default_test_id(self):
...@@ -214,19 +212,15 @@ class LibTestSuite(NoseTestSuite): ...@@ -214,19 +212,15 @@ class LibTestSuite(NoseTestSuite):
@property @property
def cmd(self): def cmd(self):
cmd = ( cmd = [
"nosetests --id-file={test_ids} {test_id} {test_opts} " "nosetests",
"--with-xunit --xunit-file={xunit_report} {extra} " "--id-file={}".format(self.test_ids),
"--verbosity={verbosity} " self.test_id,
"{passthrough}".format( ] + self.test_options_flags + [
test_ids=self.test_ids, "--with-xunit",
test_id=self.test_id, "--xunit-file={}".format(self.xunit_report),
test_opts=self.test_options_flags, self.extra_args,
xunit_report=self.xunit_report, "--verbosity={}".format(self.verbosity),
verbosity=self.verbosity, ] + self.passthrough_options
extra=self.extra_args,
passthrough=self.passthrough_options
)
)
return self._under_coverage_cmd(cmd) return self._under_coverage_cmd(cmd)
...@@ -76,7 +76,7 @@ class TestSuite(object): ...@@ -76,7 +76,7 @@ class TestSuite(object):
It returns False if errors or failures occur. Otherwise, it It returns False if errors or failures occur. Otherwise, it
returns True. returns True.
""" """
cmd = self.cmd cmd = " ".join(self.cmd)
if tasks.environment.dry_run: if tasks.environment.dry_run:
tasks.environment.info(cmd) tasks.environment.info(cmd)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment