Skip to content

Commit a28f9cf

Browse files
authored
Code reference support
1 parent 970e96d commit a28f9cf

File tree

13 files changed

+541
-152
lines changed

13 files changed

+541
-152
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ coverage.xml
3636
# Environments
3737
.env
3838
.venv
39+
/venv

.travis.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ python:
99
- "3.6"
1010
- "3.7"
1111
- "3.8"
12+
install:
13+
- pip install pycodestyle pydocstyle pytest delayed-assert requests reportportal-client dill
14+
before_script:
15+
- pycodestyle .
16+
- pydocstyle .
1217
script:
13-
- python setup.py test
18+
- pytest tests/ -s -vv
1419
- python setup.py -q install
1520

1621
jobs:

pytest_reportportal/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""This package contains Pytest agent's code for the Report Portal."""
2+
13
from .rp_logging import RPLogger, RPLogHandler
24

35
__all__ = ['RPLogger', 'RPLogHandler']

pytest_reportportal/errors.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,3 @@ class PytestWarning(UserWarning):
88
up to 3.8.0. Get rid of this code once we drop support for Pytest versions
99
below 3.8.0.
1010
"""
11-
pass

pytest_reportportal/listener.py

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,56 @@
1+
"""RPReportListener implements Pytest hooks required for item reporting."""
2+
13
import pytest
24
import logging
35
try:
4-
from html import escape # python3
6+
from html import escape # python3
57
except ImportError:
6-
from cgi import escape # python2
8+
from cgi import escape # python2
79

810

911
try:
1012
# This try/except can go away once we support pytest >= 3.3
1113
import _pytest.logging
14+
1215
PYTEST_HAS_LOGGING_PLUGIN = True
1316
from .rp_logging import RPLogHandler, patching_logger_class
1417
except ImportError:
1518
PYTEST_HAS_LOGGING_PLUGIN = False
1619

1720

1821
class RPReportListener(object):
22+
"""RPReportListener class."""
23+
1924
def __init__(self, py_test_service,
2025
log_level=logging.NOTSET,
2126
endpoint=None):
27+
"""Initialize RPReport Listener instance.
28+
29+
:param py_test_service: PyTestServiceClass instance
30+
:param log_level: One of the 'CRITICAL', 'ERROR',
31+
'WARNING','INFO','DEBUG', 'NOTSET'
32+
:param endpoint: Report Portal API endpoint
33+
"""
2234
# Test Item result
2335
self.PyTestService = py_test_service
2436
self.result = None
2537
self.issue = {}
2638
self._log_level = log_level
2739
if PYTEST_HAS_LOGGING_PLUGIN:
28-
self._log_handler = RPLogHandler(py_test_service=py_test_service,
29-
level=log_level,
30-
filter_reportportal_client_logs=True,
31-
endpoint=endpoint)
40+
self._log_handler = \
41+
RPLogHandler(py_test_service=py_test_service,
42+
level=log_level,
43+
filter_client_logs=True,
44+
endpoint=endpoint)
3245

3346
@pytest.hookimpl(hookwrapper=True)
3447
def pytest_runtest_protocol(self, item):
48+
"""
49+
Adding issues id marks to the test item.
50+
51+
:param item: Pytest.Item
52+
:return: generator object
53+
"""
3554
self._add_issue_id_marks(item)
3655
item_id = self.PyTestService.start_pytest_item(item)
3756
if PYTEST_HAS_LOGGING_PLUGIN:
@@ -48,6 +67,12 @@ def pytest_runtest_protocol(self, item):
4867

4968
@pytest.hookimpl(hookwrapper=True)
5069
def pytest_runtest_makereport(self, item):
70+
"""
71+
Change runtest_makereport function.
72+
73+
:param item: pytest.Item
74+
:return: None
75+
"""
5176
report = (yield).get_result()
5277

5378
if report.longrepr:
@@ -89,8 +114,10 @@ def _add_issue_id_marks(self, item):
89114
for issue_id in issue_ids:
90115
mark_issue = "{}:{}".format(mark.name, issue_id)
91116
try:
92-
pytest.mark._markers.add(mark_issue) # register mark in pytest,
93-
except AttributeError: # for pytest >= 4.5.0
117+
# register mark in pytest
118+
pytest.mark._markers.add(mark_issue),
119+
# for pytest >= 4.5.0
120+
except AttributeError:
94121
pass
95122
item.add_marker(mark_issue)
96123

@@ -120,11 +147,14 @@ def _add_issue_info(self, item, report):
120147
mark_comment = mark.kwargs.get("reason", mark.name)
121148
mark_comment += ":"
122149
for issue_id in issue_ids:
123-
issue_url = mark_url.format(issue_id=issue_id) if mark_url else None
124-
template = " [{issue_id}]({url})" if issue_url else " {issue_id}"
125-
mark_comment += template.format(issue_id=issue_id, url=issue_url)
150+
issue_url = mark_url.format(issue_id=issue_id) if \
151+
mark_url else None
152+
template = " [{issue_id}]({url})" if issue_url \
153+
else " {issue_id}"
154+
mark_comment += template.format(issue_id=issue_id,
155+
url=issue_url)
126156
elif "reason" in mark.kwargs:
127-
mark_comment = mark.kwargs["reason"]
157+
mark_comment = mark.kwargs["reason"]
128158

129159
if mark_comment:
130160
comment += ("\n* " if comment else "* ") + mark_comment
@@ -140,7 +170,8 @@ def _add_issue_info(self, item, report):
140170
(issue_type in getattr(self.PyTestService, 'issue_types', ())):
141171
if comment:
142172
self.issue['comment'] = comment
143-
self.issue['issueType'] = self.PyTestService.issue_types[issue_type]
173+
self.issue['issueType'] = \
174+
self.PyTestService.issue_types[issue_type]
144175
# self.issue['ignoreAnalyzer'] = True ???
145176
elif (report.when == 'setup') and report.skipped:
146177
self.issue['issueType'] = 'NOT_ISSUE'

pytest_reportportal/plugin.py

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""This module contains changed pytest for report-portal."""
2+
13
# This program is free software: you can redistribute it
24
# and/or modify it under the terms of the GPL licence
35

@@ -30,21 +32,36 @@
3032

3133
def is_master(config):
3234
"""
33-
True if the code running the given pytest.config object is running in a xdist master
34-
node or not running xdist at all.
35+
Validate slaveinput attribute.
36+
37+
True if the code running the given pytest.config object
38+
is running in a xdist master node or not running xdist at all.
3539
"""
3640
return not hasattr(config, 'slaveinput')
3741

3842

3943
@pytest.mark.optionalhook
4044
def pytest_configure_node(node):
45+
"""
46+
Configure node of tests.
47+
48+
:param node: _pytest.nodes.Node
49+
:return: pickle of RPService
50+
"""
4151
if node.config._reportportal_configured is False:
4252
# Stop now if the plugin is not properly configured
4353
return
44-
node.slaveinput['py_test_service'] = pickle.dumps(node.config.py_test_service)
54+
node.slaveinput['py_test_service'] = pickle.dumps(node.config.
55+
py_test_service)
4556

4657

4758
def pytest_sessionstart(session):
59+
"""
60+
Start test session.
61+
62+
:param session: Session
63+
:return: None
64+
"""
4865
if session.config._reportportal_configured is False:
4966
# Stop now if the plugin is not properly configured
5067
return
@@ -73,6 +90,12 @@ def pytest_sessionstart(session):
7390

7491

7592
def pytest_collection_finish(session):
93+
"""
94+
Collect tests if session is configured.
95+
96+
:param session: pytest.Session
97+
:return: None
98+
"""
7699
if session.config._reportportal_configured is False:
77100
# Stop now if the plugin is not properly configured
78101
return
@@ -81,6 +104,12 @@ def pytest_collection_finish(session):
81104

82105

83106
def wait_launch(rp_client):
107+
"""
108+
Wait for initialize RP_Service.
109+
110+
:param rp_client: RP_Service
111+
:return: None
112+
"""
84113
timeout = time.time() + LAUNCH_WAIT_TIMEOUT
85114
while not rp_client.launch_id:
86115
if time.time() > timeout:
@@ -89,6 +118,12 @@ def wait_launch(rp_client):
89118

90119

91120
def pytest_sessionfinish(session):
121+
"""
122+
Finish session if has attr 'slaveinput'.
123+
124+
:param session: pytest.Session
125+
:return: None
126+
"""
92127
if session.config._reportportal_configured is False:
93128
# Stop now if the plugin is not properly configured
94129
return
@@ -98,7 +133,12 @@ def pytest_sessionfinish(session):
98133

99134

100135
def pytest_configure(config):
136+
"""
137+
Configure RPReportListener for send logs.
101138
139+
:param config: Config file
140+
:return: None
141+
"""
102142
if config.getoption('--collect-only', default=False) or \
103143
config.getoption('--setup-plan', default=False) or \
104144
not config.option.rp_enabled:
@@ -132,12 +172,14 @@ def pytest_configure(config):
132172
if not config.option.rp_launch:
133173
config.option.rp_launch = config.getini('rp_launch')
134174
if not config.option.rp_launch_description:
135-
config.option.rp_launch_description = config.getini('rp_launch_description')
175+
config.option.rp_launch_description = config.\
176+
getini('rp_launch_description')
136177

137178
if is_master(config):
138179
config.py_test_service = PyTestServiceClass()
139180
else:
140-
config.py_test_service = pickle.loads(config.slaveinput['py_test_service'])
181+
config.py_test_service = pickle.loads(config.
182+
slaveinput['py_test_service'])
141183

142184
# set Pytest_Reporter and configure it
143185
if PYTEST_HAS_LOGGING_PLUGIN:
@@ -157,6 +199,12 @@ def pytest_configure(config):
157199

158200

159201
def pytest_unconfigure(config):
202+
"""
203+
Clear config from reporter.
204+
205+
:param config: Config file
206+
:return: None
207+
"""
160208
if config._reportportal_configured is False:
161209
# Stop now if the plugin is not properly configured
162210
return
@@ -169,6 +217,12 @@ def pytest_unconfigure(config):
169217

170218

171219
def pytest_addoption(parser):
220+
"""
221+
Add parameter in config of reporter.
222+
223+
:param parser: Config
224+
:return: None
225+
"""
172226
group = parser.getgroup('reporting')
173227
group.addoption(
174228
'--rp-launch',
@@ -179,7 +233,8 @@ def pytest_addoption(parser):
179233
'--rp-launch-description',
180234
action='store',
181235
dest='rp_launch_description',
182-
help='Launch description (overrides rp_launch_description config option)')
236+
help='Launch description (overrides '
237+
'rp_launch_description config option)')
183238

184239
group.addoption(
185240
'--reportportal',
@@ -288,7 +343,8 @@ def pytest_addoption(parser):
288343
parser.addini(
289344
'rp_issue_system_url',
290345
default='',
291-
help='URL to get issue description. Issue id from pytest mark will be added to this URL')
346+
help='URL to get issue description. Issue id '
347+
'from pytest mark will be added to this URL')
292348

293349
parser.addini(
294350
'rp_verify_ssl',
@@ -300,9 +356,12 @@ def pytest_addoption(parser):
300356
'rp_display_suite_test_file',
301357
default=True,
302358
type='bool',
303-
help="In case of True, include the suite's relative file path in the launch name as a convention of "
304-
"'<RELATIVE_FILE_PATH>::<SUITE_NAME>'. In case of False, set the launch name to be the suite name "
305-
"only - this flag is relevant only when 'rp_hierarchy_module' flag is set to False")
359+
help="In case of True, include the suite's relative"
360+
" file path in the launch name as a convention of "
361+
"'<RELATIVE_FILE_PATH>::<SUITE_NAME>'. "
362+
"In case of False, set the launch name to be the suite name "
363+
"only - this flag is relevant only when"
364+
" 'rp_hierarchy_module' flag is set to False")
306365

307366
parser.addini(
308367
'rp_issue_id_marks',

0 commit comments

Comments
 (0)