summaryrefslogtreecommitdiffstats
path: root/test/test_formatter_json.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_formatter_json.py')
-rw-r--r--test/test_formatter_json.py138
1 files changed, 138 insertions, 0 deletions
diff --git a/test/test_formatter_json.py b/test/test_formatter_json.py
new file mode 100644
index 0000000..25aa5f5
--- /dev/null
+++ b/test/test_formatter_json.py
@@ -0,0 +1,138 @@
+"""Test the codeclimate JSON formatter."""
+from __future__ import annotations
+
+import json
+import pathlib
+import subprocess
+import sys
+
+import pytest
+
+from ansiblelint.errors import MatchError
+from ansiblelint.file_utils import Lintable
+from ansiblelint.formatters import CodeclimateJSONFormatter
+from ansiblelint.rules import AnsibleLintRule
+
+
+class TestCodeclimateJSONFormatter:
+ """Unit test for CodeclimateJSONFormatter."""
+
+ rule = AnsibleLintRule()
+ matches: list[MatchError] = []
+ formatter: CodeclimateJSONFormatter | None = None
+
+ def setup_class(self) -> None:
+ """Set up few MatchError objects."""
+ self.rule = AnsibleLintRule()
+ self.rule.id = "TCF0001"
+ self.rule.severity = "VERY_HIGH"
+ self.matches = []
+ self.matches.append(
+ MatchError(
+ message="message",
+ lineno=1,
+ details="hello",
+ lintable=Lintable("filename.yml", content=""),
+ rule=self.rule,
+ ),
+ )
+ self.matches.append(
+ MatchError(
+ message="message",
+ lineno=2,
+ details="hello",
+ lintable=Lintable("filename.yml", content=""),
+ rule=self.rule,
+ ignored=True,
+ ),
+ )
+ self.formatter = CodeclimateJSONFormatter(
+ pathlib.Path.cwd(),
+ display_relative_path=True,
+ )
+
+ def test_format_list(self) -> None:
+ """Test if the return value is a string."""
+ assert isinstance(self.formatter, CodeclimateJSONFormatter)
+ assert isinstance(self.formatter.format_result(self.matches), str)
+
+ def test_result_is_json(self) -> None:
+ """Test if returned string value is a JSON."""
+ assert isinstance(self.formatter, CodeclimateJSONFormatter)
+ output = self.formatter.format_result(self.matches)
+ json.loads(output)
+ # https://github.com/ansible/ansible-navigator/issues/1490
+ assert "\n" not in output
+
+ def test_single_match(self) -> None:
+ """Test negative case. Only lists are allowed. Otherwise a RuntimeError will be raised."""
+ assert isinstance(self.formatter, CodeclimateJSONFormatter)
+ with pytest.raises(RuntimeError):
+ self.formatter.format_result(self.matches[0]) # type: ignore[arg-type]
+
+ def test_result_is_list(self) -> None:
+ """Test if the return JSON contains a list with a length of 2."""
+ assert isinstance(self.formatter, CodeclimateJSONFormatter)
+ result = json.loads(self.formatter.format_result(self.matches))
+ assert len(result) == 2
+
+ def test_validate_codeclimate_schema(self) -> None:
+ """Test if the returned JSON is a valid codeclimate report."""
+ assert isinstance(self.formatter, CodeclimateJSONFormatter)
+ result = json.loads(self.formatter.format_result(self.matches))
+ single_match = result[0]
+ assert "type" in single_match
+ assert single_match["type"] == "issue"
+ assert "check_name" in single_match
+ assert "categories" in single_match
+ assert isinstance(single_match["categories"], list)
+ assert "severity" in single_match
+ assert single_match["severity"] == "major"
+ assert "description" in single_match
+ assert "fingerprint" in single_match
+ assert "location" in single_match
+ assert "path" in single_match["location"]
+ assert single_match["location"]["path"] == self.matches[0].filename
+ assert "lines" in single_match["location"]
+ assert single_match["location"]["lines"]["begin"] == self.matches[0].lineno
+ assert "positions" not in single_match["location"]
+ # check that the 2nd match is marked as 'minor' because it was created with ignored=True
+ assert result[1]["severity"] == "minor"
+
+ def test_validate_codeclimate_schema_with_positions(self) -> None:
+ """Test if the returned JSON is a valid codeclimate report (containing 'positions' instead of 'lines')."""
+ assert isinstance(self.formatter, CodeclimateJSONFormatter)
+ result = json.loads(
+ self.formatter.format_result(
+ [
+ MatchError(
+ message="message",
+ lineno=1,
+ column=42,
+ details="hello",
+ lintable=Lintable("filename.yml", content=""),
+ rule=self.rule,
+ ),
+ ],
+ ),
+ )
+ assert result[0]["location"]["positions"]["begin"]["line"] == 1
+ assert result[0]["location"]["positions"]["begin"]["column"] == 42
+ assert "lines" not in result[0]["location"]
+
+
+def test_code_climate_parsable_ignored() -> None:
+ """Test that -p option does not alter codeclimate format."""
+ cmd = [
+ sys.executable,
+ "-m",
+ "ansiblelint",
+ "-v",
+ "-p",
+ ]
+ file = "examples/playbooks/empty_playbook.yml"
+ result = subprocess.run([*cmd, file], check=False)
+ result2 = subprocess.run([*cmd, "-p", file], check=False)
+
+ assert result.returncode == result2.returncode
+ assert result.stdout == result2.stdout