Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ xtesting.testcase =
second = xtesting.samples.second:Test
mts = xtesting.core.mts:MTSLauncher
ansible = xtesting.core.ansible:Ansible
pytest = xtesting.core.pytest:Pytest

[build_sphinx]
all_files = 1
Expand Down
62 changes: 62 additions & 0 deletions xtesting/core/pytest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#! /usr/bin/env python3

import logging
import time

import pytest
import xtesting


class Pytest(xtesting.core.testcase.TestCase):
"""pytest driver

The 'pytest driver' can be used on every test set written for pytest.
Given a pytest package that is launched with the command:

`pytest --opt1 arg1 --opt2 testdir`

it can be executed by xtesting with the following testcase.yaml:

```yaml
run:
name: pytest
args:
dir: testdir
options:
opt1: arg1
opt2: null
```

options can be written as a list of strings `['--opt1', 'arg1', '--opt2']`
"""

logger = logging.getLogger('pytest')

def run(self, **args):
# parsing args
# - 'dir' is mandatory
# - 'options' is an optional list or a dict flatten to a list
try:
dir = args.pop('dir')
options = args.pop('options', [])
if isinstance(options, dict):
options = [str(item) for opt in
zip([f'--{k}' if len(str(k)) > 1 else f'-{k}' for k in options.keys()], options.values())
for item in opt if item is not None]
except KeyError as err:
self.logger.exception(f"Missing args: {err.args[0]!r}")
return self.EX_RUN_ERROR
if args:
self.logger.exception(f"Unexpected args {args}")
return self.EX_RUN_ERROR

# running pytest with 'options' in 'dir'
# the pytesthooks initiates an empty 'details' and populates it with individual test results
self.start_time = time.time()
pytest.main(args=[dir] + ['--tb=no', '-p', 'xtesting.utils.pytesthooks'] + options)
self.stop_time = time.time()

# fectching results in pytesthooks
self.details = xtesting.utils.pytesthooks.details
self.result = xtesting.utils.pytesthooks.result
return self.EX_OK
31 changes: 31 additions & 0 deletions xtesting/utils/pytesthooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import pytest

details = None
passed = None
failed = None
result = None


def pytest_sessionstart(session):
global details, passed, failed, result
details = dict(tests=[])
passed = 0
failed = 0
result = 0


@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
global details, passed, failed, result
yreport = yield
report = yreport.get_result()
if report.when == 'call':
test = dict(name=report.nodeid, status=report.outcome.upper())
if report.passed:
passed += 1
elif report.failed:
failed += 1
test['failure'] = report.longreprtext
if passed + failed:
result = passed / (passed + failed) * 100
details['tests'].append(test)