def test_no_python_file(self): quality = QualityReporter(PylintDriver()) file_paths = ['file1.coffee', 'subdir/file2.js'] # Expect that we get no results because no Python files for path in file_paths: result = quality.violations(path) self.assertEqual(result, [])
def test_no_quality_issues_newline(self): _setup_patch((b'\n', b''), 0) # Parse the report quality = QualityReporter(PylintDriver()) self.assertEqual([], quality.violations('file1.py'))
def test_unicode_continuation_char(self): _setup_patch((b"file.py:2: [W1401]" b" Invalid char '\xc3'", ''), 0) # Since we are replacing characters we can't interpet, this should # return a valid string with the char replaced with '?' quality = QualityReporter(PylintDriver()) violations = quality.violations(u'file.py') self.assertEqual(violations, [Violation(2, u"W1401: Invalid char '\ufffd'")])
def test_no_quality_issues_emptystring(self): # Patch the output of `pylint` _setup_patch((b'', b''), 0) # Parse the report quality = QualityReporter(PylintDriver()) self.assertEqual([], quality.violations('file1.py'))
def test_non_integer_line_num(self): _setup_patch((dedent(u""" file.py:not_a_number: C0111: Missing docstring file.py:\u8911: C0111: Missing docstring """).encode('utf-8'), ''), 0) # None of the violations have a valid line number, so they should all be skipped violations = QualityReporter(PylintDriver()).violations(u'file.py') self.assertEqual(violations, [])
def test_no_quality_issues_emptystring(self): # Patch the output of `pylint` _mock_communicate = patch.object(Popen, 'communicate').start() _mock_communicate.return_value = (b'', b'') # Parse the report quality = QualityReporter(PylintDriver()) self.assertEqual([], quality.violations('file1.py'))
def test_non_integer_line_num(self): _mock_communicate = patch.object(Popen, 'communicate').start() _mock_communicate.return_value = (dedent(u""" file.py:not_a_number: C0111: Missing docstring file.py:\u8911: C0111: Missing docstring """).encode('utf-8'), '') # None of the violations have a valid line number, so they should all be skipped violations = QualityReporter(PylintDriver()).violations(u'file.py') self.assertEqual(violations, [])
def test_quality(self): # Patch the output of `pylint` _setup_patch((dedent(""" file1.py:1: [C0111] Missing docstring file1.py:1: [C0111, func_1] Missing docstring file1.py:2: [W0612, cls_name.func] Unused variable 'd' file1.py:2: [W0511] TODO: Not the real way we'll store usages! file1.py:579: [F0401] Unable to import 'rooted_paths' file1.py:113: [W0613, cache_relation.clear_pk] Unused argument 'cls' file1.py:150: [F0010] error while code parsing ([Errno 2] No such file or directory) file1.py:149: [C0324, Foo.__dict__] Comma not followed by a space self.peer_grading._find_corresponding_module_for_location(Location('i4x','a','b','c','d')) file1.py:162: [R0801] Similar lines in 2 files ==file1:162 ==student.views:4 import json import logging import random path/to/file2.py:100: [W0212, openid_login_complete] Access to a protected member """).strip().encode('ascii'), '')) expected_violations = [ Violation(1, 'C0111: Missing docstring'), Violation(1, 'C0111: func_1: Missing docstring'), Violation(2, "W0612: cls_name.func: Unused variable 'd'"), Violation(2, "W0511: TODO: Not the real way we'll store usages!"), Violation(579, "F0401: Unable to import 'rooted_paths'"), Violation( 150, "F0010: error while code parsing ([Errno 2] No such file or directory)" ), Violation(149, "C0324: Foo.__dict__: Comma not followed by a space"), Violation(162, "R0801: Similar lines in 2 files"), Violation(113, "W0613: cache_relation.clear_pk: Unused argument 'cls'") ] # Parse the report quality = QualityReporter(PylintDriver()) # Expect that the name is set self.assertEqual(quality.name(), 'pylint') # Measured_lines is undefined for a # quality reporter since all lines are measured self.assertEqual(quality.measured_lines('file1.py'), None) # Expect that we get violations for file1.py only # We're not guaranteed that the violations are returned # in any particular order. actual_violations = quality.violations('file1.py') self.assertEqual(len(actual_violations), len(expected_violations)) for expected in expected_violations: self.assertIn(expected, actual_violations)
def test_quality_error(self): # Patch the output stderr/stdout and returncode of `pylint` _setup_patch((b'file1.py:1: [C0111] Missing docstring', b'oops'), status_code=1) # Parse the report quality = QualityReporter(PylintDriver()) # Expect an error self.assertRaises(CommandError, quality.violations, 'file1.py')
def test_quality_pregenerated_report_continuation_char(self): # The report contains a non-ASCII continuation char pylint_reports = [BytesIO(b"file.py:2: [W1401] Invalid char '\xc3'")] # Generate the violation report quality = QualityReporter(PylintDriver(), reports=pylint_reports) violations = quality.violations('file.py') # Expect that the char is replaced self.assertEqual(violations, [Violation(2, u"W1401: Invalid char '\ufffd'")])
def test_quality_deprecation_warning(self): # Patch the output stderr/stdout and returncode of `pylint` _setup_patch((b'file1.py:1: [C0111] Missing docstring\n' b'file1.py:1: [C0111, func_1] Missing docstring', b'Foobar: pylintrc deprecation warning'), 0) # Parse the report quality = QualityReporter(PylintDriver()) actual_violations = quality.violations('file1.py') # Assert that pylint successfully runs and finds 2 violations self.assertEqual(len(actual_violations), 2)
def test_unicode_continuation_char(self): _mock_communicate = patch.object(Popen, 'communicate').start() # Test a unicode continuation char, which pylint can produce (probably an encoding bug in pylint) _mock_communicate.return_value = (b"file.py:2: [W1401]" b" Invalid char '\xc3'", '') # Since we are replacing characters we can't interpet, this should # return a valid string with the char replaced with '?' quality = QualityReporter(PylintDriver()) violations = quality.violations(u'file.py') self.assertEqual(violations, [Violation(2, u"W1401: Invalid char '\ufffd'")])
def test_quality_error(self): # Patch the output stderr/stdout and returncode of `pylint` _setup_patch((b'file1.py:1: [C0111] Missing docstring', b'oops'), status_code=1) # Parse the report with patch( 'diff_cover.violationsreporters.violations_reporter.run_command_for_code' ) as code: code.return_value = 0 quality = QualityReporter(PylintDriver()) # Expect an error self.assertRaises(CommandError, quality.violations, 'file1.py')
def test_quality_pregenerated_report(self): # When the user provides us with a pre-generated pylint report # then use that instead of calling pylint directly. pylint_reports = [ BytesIO( dedent(u""" path/to/file.py:1: [C0111] Missing docstring path/to/file.py:57: [W0511] TODO the name of this method is a little bit confusing another/file.py:41: [W1201, assign_default_role] Specify string format arguments as logging function parameters another/file.py:175: [C0322, Foo.bar] Operator not preceded by a space x=2+3 ^ Unicode: \u9404 \u1239 another/file.py:259: [C0103, bar] Invalid name "\u4920" for type variable (should match [a-z_][a-z0-9_]{2,30}$) """).strip().encode('utf-8')), BytesIO( dedent(u""" path/to/file.py:183: [C0103, Foo.bar.gettag] Invalid name "\u3240" for type argument (should match [a-z_][a-z0-9_]{2,30}$) another/file.py:183: [C0111, Foo.bar.gettag] Missing docstring """).strip().encode('utf-8')) ] # Generate the violation report quality = QualityReporter(PylintDriver(), reports=pylint_reports) # Expect that we get the right violations expected_violations = [ Violation(1, u'C0111: Missing docstring'), Violation( 57, u'W0511: TODO the name of this method is a little bit confusing' ), Violation( 183, u'C0103: Foo.bar.gettag: Invalid name "\u3240" for type argument (should match [a-z_][a-z0-9_]{2,30}$)' ) ] # We're not guaranteed that the violations are returned # in any particular order. actual_violations = quality.violations('path/to/file.py') self.assertEqual(len(actual_violations), len(expected_violations)) for expected in expected_violations: self.assertIn(expected, actual_violations)
def test_unicode(self): _setup_patch((dedent(u""" file_\u6729.py:616: [W1401] Anomalous backslash in string: '\u5922'. String constant might be missing an r prefix. file.py:2: [W0612, cls_name.func_\u9492] Unused variable '\u2920' """).encode('utf-8'), ''), 0) quality = QualityReporter(PylintDriver()) violations = quality.violations(u'file_\u6729.py') self.assertEqual(violations, [ Violation( 616, u"W1401: Anomalous backslash in string: '\u5922'. String constant might be missing an r prefix." ), ]) violations = quality.violations(u'file.py') self.assertEqual(violations, [ Violation( 2, u"W0612: cls_name.func_\u9492: Unused variable '\u2920'") ])
def test_unicode(self): _mock_communicate = patch.object(Popen, 'communicate').start() # Test non-ascii unicode characters in the filename, function name and message _mock_communicate.return_value = (dedent(u""" file_\u6729.py:616: [W1401] Anomalous backslash in string: '\u5922'. String constant might be missing an r prefix. file.py:2: [W0612, cls_name.func_\u9492] Unused variable '\u2920' """).encode('utf-8'), b'') quality = QualityReporter(PylintDriver()) violations = quality.violations(u'file_\u6729.py') self.assertEqual(violations, [ Violation( 616, u"W1401: Anomalous backslash in string: '\u5922'. String constant might be missing an r prefix." ), ]) violations = quality.violations(u'file.py') self.assertEqual(violations, [ Violation( 2, u"W0612: cls_name.func_\u9492: Unused variable '\u2920'") ])
def run(self): quality_driver = PylintDriver() quality_reporter = QualityReporter(driver=quality_driver) quality_percentage = generate_quality_report( tool=quality_reporter, compare_branch='origin/master') return round(quality_percentage)
flake8_driver, pyflakes_driver, PylintDriver, jshint_driver, eslint_driver, pydocstyle_driver, pycodestyle_driver, ) from diff_cover.violationsreporters.java_violations_reporter import ( CheckstyleXmlDriver, checkstyle_driver, FindbugsXmlDriver, PmdXmlDriver) QUALITY_DRIVERS = { 'cppcheck' : CppcheckDriver(), 'pycodestyle': pycodestyle_driver, 'pyflakes': pyflakes_driver, 'pylint': PylintDriver(), 'flake8': flake8_driver, 'jshint': jshint_driver, 'eslint': eslint_driver, 'pydocstyle': pydocstyle_driver, 'checkstyle': checkstyle_driver, 'checkstylexml': CheckstyleXmlDriver(), 'findbugs': FindbugsXmlDriver(), 'pmd': PmdXmlDriver() } VIOLATION_CMD_HELP = "Which code quality tool to use (%s)" % "/".join(sorted(QUALITY_DRIVERS)) INPUT_REPORTS_HELP = "Which violations reports to use" OPTIONS_HELP = "Options to be passed to the violations tool"
from diff_cover.violationsreporters.violations_reporter import ( CppcheckDriver, PylintDriver, eslint_driver, flake8_driver, jshint_driver, pycodestyle_driver, pydocstyle_driver, pyflakes_driver, ) QUALITY_DRIVERS = { "cppcheck": CppcheckDriver(), "pycodestyle": pycodestyle_driver, "pyflakes": pyflakes_driver, "pylint": PylintDriver(), "flake8": flake8_driver, "jshint": jshint_driver, "eslint": eslint_driver, "pydocstyle": pydocstyle_driver, "checkstyle": checkstyle_driver, "checkstylexml": CheckstyleXmlDriver(), "findbugs": FindbugsXmlDriver(), "pmd": PmdXmlDriver(), } VIOLATION_CMD_HELP = "Which code quality tool to use (%s)" % "/".join( sorted(QUALITY_DRIVERS)) INPUT_REPORTS_HELP = "Which violations reports to use" OPTIONS_HELP = "Options to be passed to the violations tool" INCLUDE_HELP = "Files to include (glob pattern)"
def test_no_such_file(self): quality = QualityReporter(PylintDriver()) # Expect that we get no results result = quality.violations('') self.assertEqual(result, [])