Skip to content

Commit

Permalink
Add shellcheck violation tool in diff-quality (#347)
Browse files Browse the repository at this point in the history
  • Loading branch information
mg-cloud committed Jun 11, 2023
1 parent f02f9bb commit a84e65e
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
2 changes: 2 additions & 0 deletions diff_cover/diff_quality_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
pycodestyle_driver,
pydocstyle_driver,
pyflakes_driver,
shellcheck_driver,
)

QUALITY_DRIVERS = {
Expand All @@ -69,6 +70,7 @@
"checkstylexml": CheckstyleXmlDriver(),
"findbugs": FindbugsXmlDriver(),
"pmd": PmdXmlDriver(),
"shellcheck": shellcheck_driver,
}

VIOLATION_CMD_HELP = "Which code quality tool to use (%s)" % "/".join(
Expand Down
12 changes: 12 additions & 0 deletions diff_cover/violationsreporters/violations_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,18 @@ def measured_lines(self, src_path):
command_to_check_install=["jshint", "-v"],
)

shellcheck_driver = RegexBasedDriver(
name="shellcheck",
supported_extensions=["sh"],
# Use gcc format to ease violations parsing
command=["shellcheck", "-f", "gcc"],
expression=r"^([^:]+):(\d+):(\d+: .*)$",
command_to_check_install=["shellcheck", "-V"],
# shellcheck exit code is 1 if there are violations
# https://www.shellcheck.net/wiki/Integration#exit-codes
exit_codes=[0, 1],
)


class EslintDriver(RegexBasedDriver):
def __init__(self):
Expand Down
65 changes: 65 additions & 0 deletions tests/test_violations_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
pycodestyle_driver,
pydocstyle_driver,
pyflakes_driver,
shellcheck_driver,
)


Expand Down Expand Up @@ -1712,6 +1713,70 @@ def test_report_root_path(self):
assert actual_violations == [expected_violation]


class TestShellCheckQualityReporterTest:
"""Tests for shellcheck quality violations."""

def test_no_such_file(self):
"""Expect that we get no results."""
quality = QualityReporter(shellcheck_driver)

result = quality.violations("")
assert result == []

def test_no_shell_file(self):
"""Expect that we get no results because no shell files."""
quality = QualityReporter(shellcheck_driver)
file_paths = ["file1.coffee", "subdir/file2.hs"]
for path in file_paths:
result = quality.violations(path)
assert result == []

def test_quality(self, process_patcher):
"""Integration test."""
process_patcher(
(
dedent(
"""
foo/bar/path/to/file.sh:2:18: note: Double quote to prevent globbing and word splitting. [SC2086]
foo/bar/path/to/file.sh:53:10: warning: Use 'cd ... || exit' or 'cd ... || return' in case cd fails. [SC2164]
"""
)
.strip()
.encode("ascii"),
"",
)
)

expected_violations = [
Violation(
2,
"18: note: Double quote to prevent globbing and word splitting. [SC2086]",
),
Violation(
53,
"10: warning: Use 'cd ... || exit' or 'cd ... || return' in case cd fails. [SC2164]",
),
]

# Parse the report
quality = QualityReporter(shellcheck_driver)

# Expect that the name is set
assert quality.name() == "shellcheck"

# Measured_lines is undefined for a
# quality reporter since all lines are measured
assert quality.measured_lines("foo/bar/path/to/file.sh") is 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("foo/bar/path/to/file.sh")
assert len(actual_violations) == len(expected_violations)
for expected in expected_violations:
assert expected in actual_violations


class TestSimpleCommandTestCase:
"""
Tests that the exit code detected by the method is passed as the return value of the method.
Expand Down

0 comments on commit a84e65e

Please sign in to comment.