aboutsummaryrefslogtreecommitdiffstats
path: root/xtesting/core/pytest.py
diff options
context:
space:
mode:
Diffstat (limited to 'xtesting/core/pytest.py')
-rw-r--r--xtesting/core/pytest.py101
1 files changed, 101 insertions, 0 deletions
diff --git a/xtesting/core/pytest.py b/xtesting/core/pytest.py
new file mode 100644
index 00000000..1dadf300
--- /dev/null
+++ b/xtesting/core/pytest.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2023 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Define classes required to run any Pytest suites."""
+
+import contextlib
+import io
+import logging
+import time
+
+import pytest
+
+from xtesting.core import testcase
+
+
+@pytest.hookimpl(hookwrapper=True)
+def pytest_runtest_makereport(item, call):
+ """Collect all Pytest results"""
+ # pylint: disable=unused-argument
+ yreport = yield
+ report = yreport.get_result()
+ if report.when == 'call':
+ test = {"name": report.nodeid, "status": report.outcome.upper()}
+ if report.passed:
+ Pytest.passed += 1
+ elif report.failed:
+ Pytest.failed += 1
+ test['failure'] = report.longreprtext
+ Pytest.tests.append(test)
+
+
+class Pytest(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:
+
+ .. code-block:: shell
+
+ pytest --opt1 arg1 --opt2 testdir
+
+ it can be executed by xtesting with the following testcase.yaml:
+
+ .. code-block:: yaml
+
+ run:
+ name: pytest
+ args:
+ opt1: arg1
+ opt2: arg2
+ """
+
+ __logger = logging.getLogger(__name__)
+ tests = []
+ passed = 0
+ failed = 0
+
+ def run(self, **kwargs):
+ # parsing args
+ # - 'dir' is mandatory
+ # - 'options' is an optional list or a dict flatten to a list
+ status = self.EX_RUN_ERROR
+ self.start_time = time.time()
+ try:
+ pydir = kwargs.pop('dir')
+ options = kwargs.pop('options', {})
+ options['html'] = f'{self.res_dir}/results.html'
+ options['junitxml'] = f'{self.res_dir}/results.xml'
+ if 'tb' not in options:
+ options['tb'] = 'no'
+ 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]
+ with contextlib.redirect_stdout(io.StringIO()) as output:
+ pytest.main(
+ args=[pydir] + ['-p', __name__] + options)
+ with open(f'{self.res_dir}/stdout.log',
+ 'w', encoding='utf-8') as output_file:
+ output_file.write(output.getvalue())
+ self.__logger.info(
+ "\n\n %s \n",
+ output.getvalue().splitlines()[-1].replace('=', ''))
+ self.details = Pytest.tests
+ if Pytest.passed + Pytest.failed:
+ self.result = Pytest.passed / (
+ Pytest.passed + Pytest.failed) * 100
+ status = self.EX_OK
+ except Exception: # pylint: # pylint: disable=broad-except
+ self.__logger.exception("Cannot execute pytest")
+ self.stop_time = time.time()
+ return status