Skip to content

Commit

Permalink
Add number of collected items and deselected flag to report
Browse files Browse the repository at this point in the history
  • Loading branch information
numirias committed Nov 5, 2019
1 parent 3bdc925 commit ad25036
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 22 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,15 @@ Number of outcomes per category and the total number of test items.

| Key | Description |
| --- | --- |
| `collected` | Total number of tests collected. |
| `total` | Total number of tests run. |
| `<outcome>` | Number of tests with that outcome. (absent if number is 0) |
| `total` | Total number of tests. |

#### Example

```python
{
"collected": 10,
"passed": 2,
"failed": 3,
"xfailed": 1,
Expand Down Expand Up @@ -247,6 +249,7 @@ The `result` is a list of the collected nodes:
| `nodeid` | ID of the node. |
| `type` | Type of the collected node. |
| `lineno` | Line number. (absent if not applicable) |
| `deselected` | `true` if the test is deselected. (absent if not deselected) |

#### Example

Expand All @@ -270,6 +273,7 @@ The `result` is a list of the collected nodes:
"nodeid": "test_foo.py::test_pass",
"type": "Function",
"lineno": 24,
"deselected": true
},
...
]
Expand Down
30 changes: 26 additions & 4 deletions pytest_jsonreport/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,29 @@ def pytest_sessionstart(self, session):
self._start_time = time.time()

def pytest_collectreport(self, report):
if not self._must_omit('collectors'):
self._json_collectors.append(serialize.make_collector(report))
if self._must_omit('collectors'):
return
json_result = []
for item in report.result:
json_item = serialize.make_collectitem(item)
item._json_collectitem = json_item
json_result.append(json_item)
self._json_collectors.append(serialize.make_collector(report,
json_result))

def pytest_deselected(self, items):
if self._must_omit('collectors'):
return
for item in items:
item._json_collectitem['deselected'] = True

@pytest.hookimpl(hookwrapper=True)
def pytest_collection_modifyitems(self, items):
yield
if self._must_omit('collectors'):
return
for item in items:
del item._json_collectitem

def pytest_runtest_logreport(self, report):
nodeid = report.nodeid
Expand Down Expand Up @@ -183,7 +204,8 @@ def pytest_sessionfinish(self, session):
exitcode=session.exitstatus,
root=str(session.fspath),
environment=getattr(self._config, '_metadata', {}),
summary=serialize.make_summary(self._json_tests),
summary=serialize.make_summary(self._json_tests,
collected=session.testscollected),
)
if not self._config.option.json_report_summary:
if self._json_collectors:
Expand Down Expand Up @@ -215,7 +237,7 @@ def save_report(self, path):
os.makedirs(dirname)
# Mimick FileExistsError for py2.7 compatibility
except OSError as e:
import errno
import errno # pylint: disable=import-outside-toplevel
if e.errno != errno.EEXIST:
raise
with open(path, 'w') as f:
Expand Down
34 changes: 18 additions & 16 deletions pytest_jsonreport/serialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,8 @@
from collections import Counter


def make_collector(report):
def make_collector(report, result):
"""Return JSON-serializable collector node."""
result = []
for item in report.result:
json_item = {
'nodeid': item.nodeid,
'type': item.__class__.__name__,
}
try:
location = item.location
except AttributeError:
pass
else:
json_item['lineno'] = location[1]
result.append(json_item)

collector = {
'nodeid': report.nodeid,
# This is the outcome of the collection, not the test outcome
Expand All @@ -33,6 +19,21 @@ def make_collector(report):
return collector


def make_collectitem(item):
"""Return JSON-serializable collection item."""
json_item = {
'nodeid': item.nodeid,
'type': item.__class__.__name__,
}
try:
location = item.location
except AttributeError:
pass
else:
json_item['lineno'] = location[1]
return json_item


def make_testitem(nodeid, keywords, location):
"""Return JSON-serializable test item."""
item = {
Expand Down Expand Up @@ -90,10 +91,11 @@ def make_traceback(traceback):
} for entry in traceback.reprentries]


def make_summary(tests):
def make_summary(tests, **kwargs):
"""Return JSON-serializable test result summary."""
summary = Counter([t['outcome'] for t in tests.values()])
summary['total'] = sum(summary.values())
summary.update(kwargs)
return summary


Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
packages=['pytest_jsonreport'],
author='numirias',
author_email='numirias@users.noreply.github.com',
version='1.1.0',
version='1.2.0',
url='https://github.com/numirias/pytest-json-report',
license='MIT',
install_requires=[
Expand Down
17 changes: 17 additions & 0 deletions tests/test_jsonreport.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ def test_report_summary(make_json):
'xpassed': 1,
'xfailed': 1,
'error': 2,
'collected': 10,
}


Expand Down Expand Up @@ -185,6 +186,21 @@ def test_report_crash_and_traceback(tests):
assert call['traceback'] == traceback


def test_report_item_deselected(make_json):
data = make_json("""
import pytest
@pytest.mark.good
def test_first():
pass
@pytest.mark.bad
def test_second():
pass
""", ['--json-report', '-m', 'not bad'])
assert data['summary']['collected'] == 1
assert not data['collectors'][1]['result'][0].get('deselected')
assert data['collectors'][1]['result'][1].get('deselected')


def test_no_traceback(make_json):
data = make_json(FILE, ['--json-report', '--json-report-omit=traceback'])
tests_ = tests_only(data)
Expand Down Expand Up @@ -490,6 +506,7 @@ def test_flaky_fail():
assert set(data['summary'].items()) == {
('total', 2),
('passed', 2),
('collected', 2),
}


Expand Down

0 comments on commit ad25036

Please sign in to comment.