Skip to content

Commit 8156f75

Browse files
committed
Add tests for json parsing and update README.md
1 parent c3b6e2b commit 8156f75

3 files changed

Lines changed: 156 additions & 8 deletions

File tree

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,22 @@ Example gitlab codequality report from [gitlab documentation](https://docs.gitla
1313
![Example gitlab codequality widget](https://docs.gitlab.com/ee/ci/testing/img/code_quality_widget_v13_11.png)
1414

1515
# Usage
16-
`$ mypy program.py | mypy-gitlab-code-quality`
16+
`$ mypy program.py --output=json | mypy-gitlab-code-quality`
1717

1818
This command send to `STDOUT` generated json that can be used as Code Quality report artifact.
1919

20+
Also, this script supports plain text output parsing for backward compatability but json is recommended
21+
22+
`$ mypy program.py | mypy-gitlab-code-quality`
23+
2024
## Example .gitlab-ci.yml
2125
```yaml
2226
image: python:alpine
2327
codequality:
2428
script:
2529
- pip install mypy mypy-gitlab-code-quality
26-
- mypy program.py --no-pretty > mypy-out.txt || true # "|| true" is used for preventing job fail when mypy find errors
27-
- mypy-gitlab-code-quality < mypy-out.txt > codequality.json
30+
- mypy program.py --output=json > mypy-out.json || true # "|| true" is used for preventing job fail when mypy find errors
31+
- mypy-gitlab-code-quality < mypy-out.json > codequality.json
2832
artifacts:
2933
when: always
3034
reports:
@@ -33,11 +37,11 @@ codequality:
3337
Note: if you want to use this example you should replace `program.py` with yours module names.
3438

3539
# Contributing
36-
Please run linters before creating merge request
40+
Please run linters before creating pull request
3741
```shell
3842
pip install requirements/dev.txt
3943
mypy .
4044
ruff check
4145
ruff format
4246
```
43-
Suggestions and merge requests are always welcome :)
47+
Suggestions and pull requests are always welcome :)

mypy_gitlab_code_quality/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import hashlib
44
import json
5-
import os
65
import re
76
from enum import Enum
87
from functools import reduce
@@ -40,7 +39,7 @@ def parse_issue(line: str) -> GitlabIssue | None:
4039
except json.JSONDecodeError:
4140
match = None
4241
if hint := match.get("hint"): # attach hint to message
43-
match["message"] += os.linesep + hint
42+
match["message"] += "\n" + hint
4443
else:
4544
match = re.fullmatch(
4645
r"(?P<file>.+?)"

tests.py

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from mypy_gitlab_code_quality import Severity, parse_issue
44

55

6-
class ParseIssueTestCase(unittest.TestCase):
6+
class ParsePlainTextTestCase(unittest.TestCase):
77
def test_path(self):
88
issue = parse_issue("dir/module.py:2: error: Description")
99
self.assertEqual("dir/module.py", issue["location"]["path"])
@@ -48,3 +48,148 @@ def test_column_number(self):
4848
def test_summary(self):
4949
issue = parse_issue("Found 5 errors in 1 file (checked 1 source file)")
5050
self.assertIsNone(issue)
51+
52+
53+
class ParseJsonTestCase(unittest.TestCase):
54+
def test_path(self):
55+
issue = parse_issue(
56+
r"""{
57+
"file": "dir/module.py",
58+
"line": 2,
59+
"column": 4,
60+
"message": "Description",
61+
"hint": null,
62+
"code": "error-code",
63+
"severity": "error"
64+
}"""
65+
)
66+
self.assertEqual("dir/module.py", issue["location"]["path"])
67+
68+
def test_line_number(self):
69+
issue = parse_issue(
70+
r"""{
71+
"file": "module.py",
72+
"line": 2,
73+
"column": 4,
74+
"message": "Description",
75+
"hint": null,
76+
"code": "error-code",
77+
"severity": "error"
78+
}"""
79+
)
80+
self.assertEqual(2, issue["location"]["lines"]["begin"])
81+
82+
def test_fingerprint(self):
83+
issue = parse_issue(
84+
r"""{
85+
"file": "module.py",
86+
"line": 2,
87+
"column": 4,
88+
"message": "Description",
89+
"hint": null,
90+
"code": "error-code",
91+
"severity": "error"
92+
}"""
93+
)
94+
self.assertEqual("4455bb04f307121aa95a7b3725996837", issue["fingerprint"])
95+
96+
def test_error_level_error(self):
97+
issue = parse_issue(
98+
r"""{
99+
"file": "module.py",
100+
"line": 2,
101+
"column": 4,
102+
"message": "Description",
103+
"hint": null,
104+
"code": "error-code",
105+
"severity": "error"
106+
}"""
107+
)
108+
self.assertEqual(Severity.major, issue["severity"])
109+
110+
def test_error_level_note(self):
111+
issue = parse_issue(
112+
r"""{
113+
"file": "module.py",
114+
"line": 2,
115+
"column": 4,
116+
"message": "Description",
117+
"hint": null,
118+
"code": "error-code",
119+
"severity": "note"
120+
}"""
121+
)
122+
self.assertEqual(Severity.info, issue["severity"])
123+
124+
def test_error_level_unknown(self):
125+
issue = parse_issue(
126+
r"""{
127+
"file": "module.py",
128+
"line": 2,
129+
"column": 4,
130+
"message": "Description",
131+
"hint": null,
132+
"code": "error-code",
133+
"severity": "egg"
134+
}"""
135+
)
136+
self.assertEqual(Severity.unknown, issue["severity"])
137+
138+
def test_description(self):
139+
issue = parse_issue(
140+
r"""{
141+
"file": "module.py",
142+
"line": 2,
143+
"column": 4,
144+
"message": "Description",
145+
"hint": null,
146+
"code": "error-code",
147+
"severity": "error"
148+
}"""
149+
)
150+
self.assertEqual("Description", issue["description"])
151+
152+
def test_description_with_characters(self):
153+
issue = parse_issue(
154+
r"""{
155+
"file": "module.py",
156+
"line": 2,
157+
"column": 4,
158+
"message": "Incompatible (got \"None\", expected \"Object\")",
159+
"hint": null,
160+
"code": "error-code",
161+
"severity": "error"
162+
}"""
163+
)
164+
self.assertEqual(
165+
'Incompatible (got "None", expected "Object")',
166+
issue["description"],
167+
)
168+
169+
def test_error_code(self):
170+
issue = parse_issue(
171+
r"""{
172+
"file": "module.py",
173+
"line": 2,
174+
"column": 4,
175+
"message": "Description",
176+
"hint": null,
177+
"code": "error-code",
178+
"severity": "error"
179+
}"""
180+
)
181+
self.assertEqual("error-code", issue["check_name"])
182+
183+
def test_hint(self):
184+
issue = parse_issue(
185+
r"""{
186+
"file": "module.py",
187+
"line": 2,
188+
"column": 4,
189+
"message": "Description",
190+
"hint": "Hint",
191+
"code": "error-code",
192+
"severity": "error"
193+
}"""
194+
)
195+
self.assertEqual("Description\nHint", issue["description"])

0 commit comments

Comments
 (0)