cloudbeat-pytest 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudbeat_pytest-0.0.1/PKG-INFO +36 -0
- cloudbeat_pytest-0.0.1/README.md +0 -0
- cloudbeat_pytest-0.0.1/cloudbeat_pytest.egg-info/PKG-INFO +36 -0
- cloudbeat_pytest-0.0.1/cloudbeat_pytest.egg-info/SOURCES.txt +14 -0
- cloudbeat_pytest-0.0.1/cloudbeat_pytest.egg-info/dependency_links.txt +1 -0
- cloudbeat_pytest-0.0.1/cloudbeat_pytest.egg-info/entry_points.txt +2 -0
- cloudbeat_pytest-0.0.1/cloudbeat_pytest.egg-info/top_level.txt +1 -0
- cloudbeat_pytest-0.0.1/setup.cfg +4 -0
- cloudbeat_pytest-0.0.1/setup.py +60 -0
- cloudbeat_pytest-0.0.1/src/__init__.py +0 -0
- cloudbeat_pytest-0.0.1/src/context.py +42 -0
- cloudbeat_pytest-0.0.1/src/helpers.py +84 -0
- cloudbeat_pytest-0.0.1/src/listener.py +54 -0
- cloudbeat_pytest-0.0.1/src/plugin.py +71 -0
- cloudbeat_pytest-0.0.1/src/pytest_reporter.py +53 -0
- cloudbeat_pytest-0.0.1/tests/test_plugin.py +78 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cloudbeat-pytest
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: CloudBeat Pytest Kit
|
|
5
|
+
Home-page: https://cloudbeat.io/
|
|
6
|
+
Author: CBNR Cloud Solutions LTD
|
|
7
|
+
Author-email: info@cloudbeat.io
|
|
8
|
+
License: Apache-2.0
|
|
9
|
+
Project-URL: Source, https://github.com/cloudbeat-io/cb-kit-python
|
|
10
|
+
Keywords: cloudbeat testing reporting python pytest
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Framework :: Pytest
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
16
|
+
Classifier: Topic :: Software Development :: Testing
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Requires-Python: >=3.6
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: author-email
|
|
29
|
+
Dynamic: classifier
|
|
30
|
+
Dynamic: description-content-type
|
|
31
|
+
Dynamic: home-page
|
|
32
|
+
Dynamic: keywords
|
|
33
|
+
Dynamic: license
|
|
34
|
+
Dynamic: project-url
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cloudbeat-pytest
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: CloudBeat Pytest Kit
|
|
5
|
+
Home-page: https://cloudbeat.io/
|
|
6
|
+
Author: CBNR Cloud Solutions LTD
|
|
7
|
+
Author-email: info@cloudbeat.io
|
|
8
|
+
License: Apache-2.0
|
|
9
|
+
Project-URL: Source, https://github.com/cloudbeat-io/cb-kit-python
|
|
10
|
+
Keywords: cloudbeat testing reporting python pytest
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Framework :: Pytest
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
16
|
+
Classifier: Topic :: Software Development :: Testing
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Requires-Python: >=3.6
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: author-email
|
|
29
|
+
Dynamic: classifier
|
|
30
|
+
Dynamic: description-content-type
|
|
31
|
+
Dynamic: home-page
|
|
32
|
+
Dynamic: keywords
|
|
33
|
+
Dynamic: license
|
|
34
|
+
Dynamic: project-url
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
cloudbeat_pytest.egg-info/PKG-INFO
|
|
4
|
+
cloudbeat_pytest.egg-info/SOURCES.txt
|
|
5
|
+
cloudbeat_pytest.egg-info/dependency_links.txt
|
|
6
|
+
cloudbeat_pytest.egg-info/entry_points.txt
|
|
7
|
+
cloudbeat_pytest.egg-info/top_level.txt
|
|
8
|
+
src/__init__.py
|
|
9
|
+
src/context.py
|
|
10
|
+
src/helpers.py
|
|
11
|
+
src/listener.py
|
|
12
|
+
src/plugin.py
|
|
13
|
+
src/pytest_reporter.py
|
|
14
|
+
tests/test_plugin.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cloudbeat_pytest
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from setuptools import setup
|
|
3
|
+
|
|
4
|
+
PACKAGE = "cloudbeat-pytest"
|
|
5
|
+
|
|
6
|
+
classifiers = [
|
|
7
|
+
'Development Status :: 5 - Production/Stable',
|
|
8
|
+
'Framework :: Pytest',
|
|
9
|
+
'Intended Audience :: Developers',
|
|
10
|
+
'License :: OSI Approved :: Apache Software License',
|
|
11
|
+
'Topic :: Software Development :: Quality Assurance',
|
|
12
|
+
'Topic :: Software Development :: Testing',
|
|
13
|
+
'Programming Language :: Python :: 3',
|
|
14
|
+
'Programming Language :: Python :: 3 :: Only',
|
|
15
|
+
'Programming Language :: Python :: 3.7',
|
|
16
|
+
'Programming Language :: Python :: 3.8',
|
|
17
|
+
'Programming Language :: Python :: 3.9',
|
|
18
|
+
'Programming Language :: Python :: 3.10',
|
|
19
|
+
'Programming Language :: Python :: 3.11',
|
|
20
|
+
'Programming Language :: Python :: 3.12',
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
install_requires = [
|
|
24
|
+
"attrs>=16.0.0",
|
|
25
|
+
"pluggy>=0.4.0",
|
|
26
|
+
"cloudbeat_common"
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
def get_readme(fname):
|
|
30
|
+
return open(os.path.join(os.path.dirname(__file__), fname)).read()
|
|
31
|
+
|
|
32
|
+
def main():
|
|
33
|
+
setup(
|
|
34
|
+
name=PACKAGE,
|
|
35
|
+
version="0.0.1", # Hardcoded version here
|
|
36
|
+
description="CloudBeat Pytest Kit",
|
|
37
|
+
url="https://cloudbeat.io/",
|
|
38
|
+
project_urls={
|
|
39
|
+
"Source": "https://github.com/cloudbeat-io/cb-kit-python",
|
|
40
|
+
},
|
|
41
|
+
author="CBNR Cloud Solutions LTD",
|
|
42
|
+
author_email="info@cloudbeat.io",
|
|
43
|
+
license="Apache-2.0",
|
|
44
|
+
classifiers=classifiers,
|
|
45
|
+
keywords="cloudbeat testing reporting python pytest",
|
|
46
|
+
# long_description=get_readme("README.md"),
|
|
47
|
+
long_description_content_type="text/markdown",
|
|
48
|
+
packages=["cloudbeat_pytest"],
|
|
49
|
+
package_dir={"cloudbeat_pytest": 'src'},
|
|
50
|
+
entry_points={"pytest11": ["cloudbeat_pytest = cloudbeat_pytest.plugin"]},
|
|
51
|
+
py_modules=['cloudbeat_pytest'],
|
|
52
|
+
python_requires='>=3.6',
|
|
53
|
+
|
|
54
|
+
# COMMENTED OUT OLD CODE
|
|
55
|
+
# setup_requires=["setuptools_scm"],
|
|
56
|
+
# use_scm_version=prepare_version,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
if __name__ == '__main__':
|
|
60
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from cloudbeat_pytest.pytest_reporter import CbPyTestReporter
|
|
2
|
+
import importlib
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CbContext:
|
|
7
|
+
class __CbContext:
|
|
8
|
+
_reporter: CbPyTestReporter = None
|
|
9
|
+
|
|
10
|
+
def __init__(self, reporter: CbPyTestReporter):
|
|
11
|
+
self._reporter = reporter
|
|
12
|
+
|
|
13
|
+
def get_webdriver_listener(self):
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
instance = None
|
|
17
|
+
|
|
18
|
+
def __new__(cls): # __new__ always a classmethod
|
|
19
|
+
if not CbContext.instance:
|
|
20
|
+
CbContext.instance = CbContext.__Report()
|
|
21
|
+
return CbContext.instance
|
|
22
|
+
|
|
23
|
+
def __getattr__(self, name):
|
|
24
|
+
return getattr(self.instance, name)
|
|
25
|
+
|
|
26
|
+
# def __setattr__(self, name):
|
|
27
|
+
# return setattr(self.instance, name)
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def init(reporter: CbPyTestReporter):
|
|
31
|
+
if not CbContext.instance:
|
|
32
|
+
CbContext.instance = CbContext.__CbContext(reporter)
|
|
33
|
+
print(sys.modules)
|
|
34
|
+
if "cloudbeat_playwright" in sys.modules:
|
|
35
|
+
pw_module = importlib.import_module(".wrapper", "cloudbeat_playwright")
|
|
36
|
+
pw_wrapper_class = getattr(pw_module, "CbPlaywrightWrapper")
|
|
37
|
+
CbContext.instance.__setattr__("pw", pw_wrapper_class(reporter))
|
|
38
|
+
if "cloudbeat_selenium" in sys.modules:
|
|
39
|
+
se_module = importlib.import_module("wrapper", "cloudbeat_selenium")
|
|
40
|
+
se_wrapper_class = getattr(se_module, "CbSeleniumWrapper")
|
|
41
|
+
CbContext.instance.__setattr__("se", se_wrapper_class(reporter))
|
|
42
|
+
return CbContext.instance
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from itertools import chain, islice
|
|
3
|
+
|
|
4
|
+
from _pytest.doctest import DoctestItem
|
|
5
|
+
from _pytest.nodes import Item
|
|
6
|
+
from _pytest.python import Class, Function, Module
|
|
7
|
+
from _pytest.reports import TestReport
|
|
8
|
+
from cloudbeat_common.models import TestStatus
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_module_details(item: Item):
|
|
12
|
+
head, maybe_class, tail = islice(chain(item.nodeid.split('::'), [None], [None]), 3)
|
|
13
|
+
class_name = maybe_class if tail else None
|
|
14
|
+
file_name, path = islice(chain(reversed(head.rsplit('/', 1)), [None]), 2)
|
|
15
|
+
module_name = file_name.split('.')[0]
|
|
16
|
+
package_name = path.replace('/', '.') if path else None
|
|
17
|
+
fqn = f"{package_name + '.' if package_name is not None else ''}{module_name}"
|
|
18
|
+
return {
|
|
19
|
+
"package_name": package_name,
|
|
20
|
+
"module_name": module_name,
|
|
21
|
+
"class_name": class_name,
|
|
22
|
+
"fqn": fqn
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_test_details(item: Item):
|
|
27
|
+
return {
|
|
28
|
+
"fqn": item.nodeid,
|
|
29
|
+
"name": item.name
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def calculate_status(result: TestReport):
|
|
34
|
+
if result.skipped:
|
|
35
|
+
return TestStatus.SKIPPED
|
|
36
|
+
elif result.failed:
|
|
37
|
+
return TestStatus.FAILED
|
|
38
|
+
return TestStatus.PASSED
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_description(item):
|
|
42
|
+
if isinstance(item, (Class, Function, Module, Item)):
|
|
43
|
+
if hasattr(item, "obj"):
|
|
44
|
+
doc = item.obj.__doc__
|
|
45
|
+
if doc is not None:
|
|
46
|
+
return trim_docstring(doc)
|
|
47
|
+
if isinstance(item, DoctestItem):
|
|
48
|
+
return item.reportinfo()[2]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def trim_docstring(docstring: str) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Convert docstring.
|
|
54
|
+
|
|
55
|
+
:param docstring: input docstring
|
|
56
|
+
:return: trimmed docstring
|
|
57
|
+
"""
|
|
58
|
+
if not docstring:
|
|
59
|
+
return ''
|
|
60
|
+
# Convert tabs to spaces (following the normal Python rules)
|
|
61
|
+
# and split into a list of lines:
|
|
62
|
+
lines = docstring.expandtabs().splitlines()
|
|
63
|
+
# Determine minimum indentation (first line doesn't count):
|
|
64
|
+
indent = sys.maxsize
|
|
65
|
+
for line in lines[1:]:
|
|
66
|
+
stripped = line.lstrip()
|
|
67
|
+
if stripped:
|
|
68
|
+
indent = min(indent, len(line) - len(stripped))
|
|
69
|
+
# Remove indentation (first line is special):
|
|
70
|
+
trimmed = [lines[0].strip()]
|
|
71
|
+
if indent < sys.maxsize:
|
|
72
|
+
for line in lines[1:]:
|
|
73
|
+
trimmed.append(line[indent:].rstrip())
|
|
74
|
+
# Strip off trailing and leading blank lines:
|
|
75
|
+
while trimmed and not trimmed[-1]:
|
|
76
|
+
trimmed.pop()
|
|
77
|
+
while trimmed and not trimmed[0]:
|
|
78
|
+
trimmed.pop(0)
|
|
79
|
+
# Return a single string:
|
|
80
|
+
return '\n'.join(trimmed)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_test_parameters(item: Item):
|
|
84
|
+
return item.callspec.params if hasattr(item, 'callspec') else None
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from cloudbeat_pytest.pytest_reporter import CbPyTestReporter
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CbTestListener:
|
|
7
|
+
|
|
8
|
+
def __init__(self, config):
|
|
9
|
+
self.config = config
|
|
10
|
+
|
|
11
|
+
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
|
|
12
|
+
def pytest_runtest_protocol(self, item):
|
|
13
|
+
reporter: CbPyTestReporter = item.config.cb_reporter
|
|
14
|
+
print(f"Starting protocol: {item.name}")
|
|
15
|
+
reporter.start_protocol(item)
|
|
16
|
+
result = (yield).get_result()
|
|
17
|
+
reporter.end_protocol(item)
|
|
18
|
+
print(f"Finished protocol: {item.name}")
|
|
19
|
+
|
|
20
|
+
@pytest.hookimpl(hookwrapper=True)
|
|
21
|
+
def pytest_runtest_setup(self, item):
|
|
22
|
+
reporter: CbPyTestReporter = item.config.cb_reporter
|
|
23
|
+
reporter.start_setup(item)
|
|
24
|
+
print(f"Starting setup hook: {item.name}")
|
|
25
|
+
yield
|
|
26
|
+
print(f"Finished setup hook: {item.name}")
|
|
27
|
+
|
|
28
|
+
@pytest.hookimpl(hookwrapper=True)
|
|
29
|
+
def pytest_runtest_teardown(self, item):
|
|
30
|
+
reporter: CbPyTestReporter = item.config.cb_reporter
|
|
31
|
+
reporter.start_teardown(item)
|
|
32
|
+
print(f"Starting teardown hook: {item.name}")
|
|
33
|
+
yield
|
|
34
|
+
print(f"Finished teardown hook: {item.name}")
|
|
35
|
+
|
|
36
|
+
@pytest.hookimpl(hookwrapper=True)
|
|
37
|
+
def pytest_runtest_call(self, item):
|
|
38
|
+
print(f"Starting call hook: {item.name}")
|
|
39
|
+
yield
|
|
40
|
+
print(f"Finished call hook: {item.name}")
|
|
41
|
+
|
|
42
|
+
@pytest.hookimpl(hookwrapper=True)
|
|
43
|
+
def pytest_runtest_makereport(self, item, call):
|
|
44
|
+
reporter: CbPyTestReporter = item.config.cb_reporter
|
|
45
|
+
print(f"Starting makereport hook: {item.name}")
|
|
46
|
+
result = (yield).get_result()
|
|
47
|
+
if call.when == "call":
|
|
48
|
+
reporter.end_call(item, result)
|
|
49
|
+
elif call.when == "setup":
|
|
50
|
+
reporter.end_setup(item, result)
|
|
51
|
+
elif call.when == "teardown":
|
|
52
|
+
reporter.end_teardown(item, result)
|
|
53
|
+
# call.when
|
|
54
|
+
print(f"Finished makereport hook: {item.name}")
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from cloudbeat_common.models import CbConfig
|
|
5
|
+
|
|
6
|
+
from cloudbeat_pytest.listener import CbTestListener
|
|
7
|
+
from cloudbeat_pytest.pytest_reporter import CbPyTestReporter
|
|
8
|
+
|
|
9
|
+
from cloudbeat_pytest.context import CbContext
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def pytest_addoption(parser):
|
|
13
|
+
group = parser.getgroup("cloudbeat")
|
|
14
|
+
group.addoption(
|
|
15
|
+
"--name",
|
|
16
|
+
action="store",
|
|
17
|
+
dest="name",
|
|
18
|
+
default="World",
|
|
19
|
+
help='Default "name" for hello().',
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_cb_config(config):
|
|
24
|
+
cb_config = CbConfig()
|
|
25
|
+
# if os.environ.get("CB_AGENT") is not None and os.environ["CB_AGENT"] == "true":
|
|
26
|
+
# cb_config.is_ready = True
|
|
27
|
+
cb_config.is_ready = True
|
|
28
|
+
cb_config.run_id = os.environ.get("CB_RUN_ID")
|
|
29
|
+
cb_config.instance_id = os.environ.get("CB_INSTANCE_ID")
|
|
30
|
+
cb_config.project_id = os.environ.get("CB_PROJECT_ID")
|
|
31
|
+
cb_config.api_endpoint_url = os.environ.get("CB_API_URL")
|
|
32
|
+
cb_config.api_token = os.environ.get("CB_API_KEY")
|
|
33
|
+
cb_config.selenium_url = os.environ.get("CB_SELENIUM_URL")
|
|
34
|
+
cb_config.appium_url = os.environ.get("CB_APPIUM_URL")
|
|
35
|
+
if os.environ.get("CB_BROWSER_NAME") is not None:
|
|
36
|
+
cb_config.capabilities["browserName"] = os.environ["CB_BROWSER_NAME"]
|
|
37
|
+
return cb_config
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def pytest_configure(config):
|
|
41
|
+
print("--- pytest_configure")
|
|
42
|
+
# if not config.option.cb_enabled:
|
|
43
|
+
# return
|
|
44
|
+
cb_config: CbConfig = get_cb_config(config)
|
|
45
|
+
if not cb_config.is_ready:
|
|
46
|
+
return
|
|
47
|
+
config.cb_reporter = CbPyTestReporter(cb_config)
|
|
48
|
+
test_listener = CbTestListener(config)
|
|
49
|
+
config.pluginmanager.register(test_listener, 'cloudbeat_listener')
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def pytest_sessionstart(session):
|
|
53
|
+
if session.config.cb_reporter is None:
|
|
54
|
+
return
|
|
55
|
+
reporter: CbPyTestReporter = session.config.cb_reporter
|
|
56
|
+
reporter.start_instance()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def pytest_sessionfinish(session):
|
|
60
|
+
if session.config.cb_reporter is None:
|
|
61
|
+
return
|
|
62
|
+
reporter: CbPyTestReporter = session.config.cb_reporter
|
|
63
|
+
reporter.end_instance()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@pytest.fixture(scope="session")
|
|
67
|
+
# instantiates ini file parses object
|
|
68
|
+
def cbx(request) -> CbContext:
|
|
69
|
+
reporter = request.session.config.cb_reporter
|
|
70
|
+
context = CbContext.init(reporter)
|
|
71
|
+
return context
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from cloudbeat_common.reporter import CbTestReporter
|
|
2
|
+
from cloudbeat_common.models import TestStatus
|
|
3
|
+
from _pytest.nodes import Item
|
|
4
|
+
from _pytest.reports import TestReport
|
|
5
|
+
from cloudbeat_pytest.helpers import get_module_details, get_test_details, calculate_status, get_description, get_test_parameters
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CbPyTestReporter(CbTestReporter):
|
|
9
|
+
def start_protocol(self, item: Item):
|
|
10
|
+
# Check if current test's module has already a related suite result
|
|
11
|
+
module_details = get_module_details(item)
|
|
12
|
+
current_suite_result = self._context["suite"] if "suite" in self._context else None
|
|
13
|
+
if current_suite_result is None or current_suite_result.fqn != module_details["fqn"]:
|
|
14
|
+
CbTestReporter.start_suite(self, module_details["module_name"], module_details["fqn"])
|
|
15
|
+
test_details = get_test_details(item)
|
|
16
|
+
case_result = CbTestReporter.start_case(self, test_details["name"], test_details["fqn"])
|
|
17
|
+
# Set case status as SKIPPED by default, because if the test is skipped,
|
|
18
|
+
# pytest_runtest_call hook won't be called and we won't get any indication
|
|
19
|
+
# if the test has been skipped
|
|
20
|
+
case_result.status = TestStatus.SKIPPED
|
|
21
|
+
case_result.description = get_description(item)
|
|
22
|
+
test_parameters = get_test_parameters(item)
|
|
23
|
+
if test_parameters is not None and len(test_parameters) > 0:
|
|
24
|
+
case_result.add_parameters(test_parameters)
|
|
25
|
+
|
|
26
|
+
def end_protocol(self, item: Item):
|
|
27
|
+
# Call end_case again (previously called in end_call),
|
|
28
|
+
# so end_time will include teardown hook
|
|
29
|
+
CbTestReporter.end_case(self)
|
|
30
|
+
# Check if current test's module has already a related suite result
|
|
31
|
+
module_details = get_module_details(item)
|
|
32
|
+
suite_result = self._context["suite"] if "suite" in self._context else None
|
|
33
|
+
if suite_result is None or suite_result.fqn != module_details["fqn"]:
|
|
34
|
+
next(suite_result for suite in self.result.suites if suite.fqn == module_details["fqn"])
|
|
35
|
+
if suite_result is None:
|
|
36
|
+
return
|
|
37
|
+
suite_result.end()
|
|
38
|
+
|
|
39
|
+
def start_setup(self, item: Item):
|
|
40
|
+
CbTestReporter.start_case_hook(self, "setup")
|
|
41
|
+
|
|
42
|
+
def end_setup(self, item: Item, result: TestReport):
|
|
43
|
+
CbTestReporter.end_case_hook(self)
|
|
44
|
+
|
|
45
|
+
def start_teardown(self, item: Item):
|
|
46
|
+
CbTestReporter.start_case_hook(self, "teardown")
|
|
47
|
+
|
|
48
|
+
def end_teardown(self, item: Item, result: TestReport):
|
|
49
|
+
CbTestReporter.end_case_hook(self)
|
|
50
|
+
|
|
51
|
+
def end_call(self, item: Item, result: TestReport):
|
|
52
|
+
status = calculate_status(result)
|
|
53
|
+
CbTestReporter.end_case(self, status)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import sys
|
|
3
|
+
import cloudbeat_playwright
|
|
4
|
+
|
|
5
|
+
class TestExample:
|
|
6
|
+
@pytest.fixture(autouse=True)
|
|
7
|
+
def setup(self):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
def test_example1(self, pytester):
|
|
11
|
+
# create a temporary conftest.py file
|
|
12
|
+
pytester.makeconftest(
|
|
13
|
+
"""
|
|
14
|
+
import pytest
|
|
15
|
+
|
|
16
|
+
# pytest_plugins = 'cloudbeat_pytest'
|
|
17
|
+
|
|
18
|
+
@pytest.fixture(params=[
|
|
19
|
+
"Brianna",
|
|
20
|
+
"Andreas",
|
|
21
|
+
"Floris",
|
|
22
|
+
])
|
|
23
|
+
def name(request):
|
|
24
|
+
return request.param
|
|
25
|
+
"""
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# create a temporary pytest test file
|
|
29
|
+
pytester.makepyfile(
|
|
30
|
+
"""
|
|
31
|
+
def test_hello_world(hello):
|
|
32
|
+
print("Hello World")
|
|
33
|
+
assert hello() == "Hello World!"
|
|
34
|
+
"""
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# run all tests with pytest
|
|
38
|
+
result = pytester.runpytest("-p", "cloudbeat_pytest")
|
|
39
|
+
|
|
40
|
+
# check that all 4 tests passed
|
|
41
|
+
result.assert_outcomes(passed=1)
|
|
42
|
+
|
|
43
|
+
def test_hello_world(self, hello, cbx):
|
|
44
|
+
print("Hello World")
|
|
45
|
+
assert hello() == "Hello World!"
|
|
46
|
+
|
|
47
|
+
@pytest.mark.regression
|
|
48
|
+
def test_example2(self, cbx):
|
|
49
|
+
cbx.pw.hello("ups")
|
|
50
|
+
"""This is test_example2 test item."""
|
|
51
|
+
assert 1 == 1
|
|
52
|
+
|
|
53
|
+
def test_parameterization(self, letter):
|
|
54
|
+
print("\n Running test_parameterization with {}".format(letter))
|
|
55
|
+
|
|
56
|
+
def test_modes(self, mode):
|
|
57
|
+
print("\n Running test_modes with {}".format(mode))
|
|
58
|
+
|
|
59
|
+
@pytest.mark.skip
|
|
60
|
+
def test_broken_feature(self, ):
|
|
61
|
+
# Always skipped!
|
|
62
|
+
assert False
|
|
63
|
+
|
|
64
|
+
@pytest.fixture(params=["a", "b", "c", "d", "e"])
|
|
65
|
+
def letter(self, request):
|
|
66
|
+
"""
|
|
67
|
+
Fixtures with parameters will run once per param
|
|
68
|
+
(You can access the current param via the request fixture)
|
|
69
|
+
"""
|
|
70
|
+
yield request.param
|
|
71
|
+
|
|
72
|
+
@pytest.fixture(params=[1, 2, 3], ids=['foo', 'bar', 'baz'])
|
|
73
|
+
def mode(self, request):
|
|
74
|
+
"""
|
|
75
|
+
Fixtures with parameters will run once per param
|
|
76
|
+
(You can access the current param via the request fixture)
|
|
77
|
+
"""
|
|
78
|
+
yield request.param
|