Commit 73966d1a by Robert Raposa

Add output of violation counts by rule

parent dced13a8
...@@ -15,11 +15,17 @@ show_help() { ...@@ -15,11 +15,17 @@ show_help() {
echo "Runs the Safe Template Linter against all files in a git commit." echo "Runs the Safe Template Linter against all files in a git commit."
echo "" echo ""
echo "Mandatory arguments to long options are mandatory for short options too." echo "Mandatory arguments to long options are mandatory for short options too."
echo " -h, --help Output this help."
echo " -m, --main-branch=COMMIT Run against files changed between the" echo " -m, --main-branch=COMMIT Run against files changed between the"
echo " current branch and this commit." echo " current branch and this commit."
echo " Defaults to origin/master." echo " Defaults to origin/master."
echo "" echo ""
echo "For additional help:" echo "This scripts does not give a grand total. Be sure to check for"
echo "0 violations on each file."
echo ""
echo "For more help using the safe template linter, including details on how"
echo "to understand and fix any violations, read the docs here:"
echo ""
echo " http://edx.readthedocs.org/projects/edx-developer-guide/en/latest/conventions/safe_templates.html#safe-template-linter" echo " http://edx.readthedocs.org/projects/edx-developer-guide/en/latest/conventions/safe_templates.html#safe-template-linter"
} }
......
<%= invalid %> <%=
'multi-line invalid'
%>
...@@ -10,8 +10,8 @@ import textwrap ...@@ -10,8 +10,8 @@ import textwrap
from unittest import TestCase from unittest import TestCase
from ..safe_template_linter import ( from ..safe_template_linter import (
_process_os_walk, FileResults, JavaScriptLinter, MakoTemplateLinter, ParseString, _lint, FileResults, JavaScriptLinter, MakoTemplateLinter, ParseString,
StringLines, PythonLinter, UnderscoreTemplateLinter, Rules StringLines, PythonLinter, SummaryResults, UnderscoreTemplateLinter, Rules
) )
...@@ -83,6 +83,15 @@ class TestSafeTemplateLinter(TestCase): ...@@ -83,6 +83,15 @@ class TestSafeTemplateLinter(TestCase):
Test some top-level linter functions Test some top-level linter functions
""" """
def setUp(self):
"""
Setup patches on linters for testing.
"""
self.patch_is_valid_directory(MakoTemplateLinter)
self.patch_is_valid_directory(JavaScriptLinter)
self.patch_is_valid_directory(UnderscoreTemplateLinter)
self.patch_is_valid_directory(PythonLinter)
def patch_is_valid_directory(self, linter_class): def patch_is_valid_directory(self, linter_class):
""" """
Creates a mock patch for _is_valid_directory on a Linter to always Creates a mock patch for _is_valid_directory on a Linter to always
...@@ -96,37 +105,137 @@ class TestSafeTemplateLinter(TestCase): ...@@ -96,37 +105,137 @@ class TestSafeTemplateLinter(TestCase):
self.addCleanup(patcher.stop) self.addCleanup(patcher.stop)
return patch_start return patch_start
def test_process_os_walk(self): def test_lint_defaults(self):
""" """
Tests the top-level processing of template files, including Mako Tests the top-level linting with default options.
includes.
""" """
out = StringIO() out = StringIO()
summary_results = SummaryResults()
options = {
'list_files': False, _lint(
'verbose': False, 'scripts/tests/templates',
} template_linters=[MakoTemplateLinter(), UnderscoreTemplateLinter(), JavaScriptLinter(), PythonLinter()],
options={
template_linters = [MakoTemplateLinter(), JavaScriptLinter(), UnderscoreTemplateLinter(), PythonLinter()] 'list_files': False,
'verbose': False,
self.patch_is_valid_directory(MakoTemplateLinter) 'rule_totals': False,
self.patch_is_valid_directory(JavaScriptLinter) },
self.patch_is_valid_directory(UnderscoreTemplateLinter) summary_results=summary_results,
self.patch_is_valid_directory(PythonLinter) out=out,
)
num_violations = _process_os_walk('scripts/tests/templates', template_linters, options, out)
output = out.getvalue() output = out.getvalue()
self.assertEqual(num_violations, 7) # Assert violation details are displayed.
self.assertIsNotNone(re.search('test\.html.*{}'.format(Rules.mako_missing_default.rule_id), output)) self.assertIsNotNone(re.search('test\.html.*{}'.format(Rules.mako_missing_default.rule_id), output))
self.assertIsNotNone(re.search('test\.coffee.*{}'.format(Rules.javascript_concat_html.rule_id), output)) self.assertIsNotNone(re.search('test\.coffee.*{}'.format(Rules.javascript_concat_html.rule_id), output))
self.assertIsNotNone(re.search('test\.coffee.*{}'.format(Rules.underscore_not_escaped.rule_id), output)) self.assertIsNotNone(re.search('test\.coffee.*{}'.format(Rules.underscore_not_escaped.rule_id), output))
self.assertIsNotNone(re.search('test\.js.*{}'.format(Rules.javascript_concat_html.rule_id), output)) self.assertIsNotNone(re.search('test\.js.*{}'.format(Rules.javascript_concat_html.rule_id), output))
self.assertIsNotNone(re.search('test\.js.*{}'.format(Rules.underscore_not_escaped.rule_id), output)) self.assertIsNotNone(re.search('test\.js.*{}'.format(Rules.underscore_not_escaped.rule_id), output))
self.assertIsNotNone(re.search('test\.underscore.*{}'.format(Rules.underscore_not_escaped.rule_id), output)) lines_with_rule = 0
lines_without_rule = 0 # Output with verbose setting only.
for underscore_match in re.finditer('test\.underscore:.*\n', output):
if re.search(Rules.underscore_not_escaped.rule_id, underscore_match.group()) is not None:
lines_with_rule += 1
else:
lines_without_rule += 1
self.assertGreaterEqual(lines_with_rule, 1)
self.assertEquals(lines_without_rule, 0)
self.assertIsNone(re.search('test\.py.*{}'.format(Rules.python_parse_error.rule_id), output)) self.assertIsNone(re.search('test\.py.*{}'.format(Rules.python_parse_error.rule_id), output))
self.assertIsNotNone(re.search('test\.py.*{}'.format(Rules.python_wrap_html.rule_id), output)) self.assertIsNotNone(re.search('test\.py.*{}'.format(Rules.python_wrap_html.rule_id), output))
# Assert no rule totals.
self.assertIsNone(re.search('{}:\s*{} violations'.format(Rules.python_parse_error.rule_id, 0), output))
# Assert final total
self.assertIsNotNone(re.search('{} violations total'.format(7), output))
def test_lint_with_verbose(self):
"""
Tests the top-level linting with verbose option.
"""
out = StringIO()
summary_results = SummaryResults()
_lint(
'scripts/tests/templates',
template_linters=[MakoTemplateLinter(), UnderscoreTemplateLinter(), JavaScriptLinter(), PythonLinter()],
options={
'list_files': False,
'verbose': True,
'rule_totals': False,
},
summary_results=summary_results,
out=out,
)
output = out.getvalue()
lines_with_rule = 0
lines_without_rule = 0 # Output with verbose setting only.
for underscore_match in re.finditer('test\.underscore:.*\n', output):
if re.search(Rules.underscore_not_escaped.rule_id, underscore_match.group()) is not None:
lines_with_rule += 1
else:
lines_without_rule += 1
self.assertGreaterEqual(lines_with_rule, 1)
self.assertGreaterEqual(lines_without_rule, 1)
# Assert no rule totals.
self.assertIsNone(re.search('{}:\s*{} violations'.format(Rules.python_parse_error.rule_id, 0), output))
# Assert final total
self.assertIsNotNone(re.search('{} violations total'.format(7), output))
def test_lint_with_rule_totals(self):
"""
Tests the top-level linting with rule totals option.
"""
out = StringIO()
summary_results = SummaryResults()
_lint(
'scripts/tests/templates',
template_linters=[MakoTemplateLinter(), UnderscoreTemplateLinter(), JavaScriptLinter(), PythonLinter()],
options={
'list_files': False,
'verbose': False,
'rule_totals': True,
},
summary_results=summary_results,
out=out,
)
output = out.getvalue()
self.assertIsNotNone(re.search('test\.py.*{}'.format(Rules.python_wrap_html.rule_id), output))
# Assert totals output.
self.assertIsNotNone(re.search('{}:\s*{} violations'.format(Rules.python_parse_error.rule_id, 0), output))
self.assertIsNotNone(re.search('{}:\s*{} violations'.format(Rules.python_wrap_html.rule_id, 1), output))
self.assertIsNotNone(re.search('{} violations total'.format(7), output))
def test_lint_with_list_files(self):
"""
Tests the top-level linting with list files option.
"""
out = StringIO()
summary_results = SummaryResults()
_lint(
'scripts/tests/templates',
template_linters=[MakoTemplateLinter(), UnderscoreTemplateLinter(), JavaScriptLinter(), PythonLinter()],
options={
'list_files': True,
'verbose': False,
'rule_totals': False,
},
summary_results=summary_results,
out=out,
)
output = out.getvalue()
# Assert file with rule is not output.
self.assertIsNone(re.search('test\.py.*{}'.format(Rules.python_wrap_html.rule_id), output))
# Assert file is output.
self.assertIsNotNone(re.search('test\.py', output))
# Assert no totals.
self.assertIsNone(re.search('{}:\s*{} violations'.format(Rules.python_parse_error.rule_id, 0), output))
self.assertIsNone(re.search('{} violations total'.format(7), output))
@ddt @ddt
......
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