tir-framework 2.5.0__tar.gz → 2.7.0__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.
- {tir_framework-2.5.0/tir_framework.egg-info → tir_framework-2.7.0}/PKG-INFO +2 -2
- {tir_framework-2.5.0 → tir_framework-2.7.0}/README.md +1 -1
- tir_framework-2.7.0/tests/test_log.py +123 -0
- tir_framework-2.7.0/tests/test_utils.py +238 -0
- tir_framework-2.7.0/tests/test_webapp_internal_clicktree.py +431 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/main.py +176 -17
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/base.py +88 -14
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/config.py +4 -1
- tir_framework-2.7.0/tir/technologies/core/events.py +23 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/language.py +78 -6
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/log.py +76 -4
- tir_framework-2.7.0/tir/technologies/core/router.py +157 -0
- tir_framework-2.7.0/tir/technologies/core/utils.py +74 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/poui_internal.py +1573 -256
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/webapp_internal.py +1949 -1234
- tir_framework-2.7.0/tir/version.py +1 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0/tir_framework.egg-info}/PKG-INFO +2 -2
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir_framework.egg-info/SOURCES.txt +6 -0
- tir_framework-2.5.0/tir/version.py +0 -1
- {tir_framework-2.5.0 → tir_framework-2.7.0}/LICENSE +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/MANIFEST.in +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/setup.cfg +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/setup.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/__init__.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/apw_internal.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/base_database.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/data/sx3.csv +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/drivers/linux64/geckodriver +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/drivers/windows/chromedriver.exe +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/drivers/windows/electron/chromedriver.exe +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/drivers/windows/geckodriver.exe +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/enumerations.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/logging_config.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/numexec.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/psutil_info.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/third_party/screen_size.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir/technologies/core/third_party/xpath_soup.py +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir_framework.egg-info/dependency_links.txt +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir_framework.egg-info/requires.txt +0 -0
- {tir_framework-2.5.0 → tir_framework-2.7.0}/tir_framework.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tir_framework
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: Test Interface Robot
|
|
5
5
|
Home-page: https://github.com/totvs/tir
|
|
6
6
|
Download-URL: https://github.com/totvs/tir
|
|
@@ -192,7 +192,7 @@ Após a configuração do ambiente virtual iremos definir o interpretador do VSc
|
|
|
192
192
|
|
|
193
193
|
## Contact
|
|
194
194
|
|
|
195
|
-
[Gitter](https://gitter.im
|
|
195
|
+
[Gitter](https://app.element.io/#/room/#totvs-tir_General:gitter.im)
|
|
196
196
|
|
|
197
197
|
## Contributing
|
|
198
198
|
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import tempfile
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import types
|
|
4
|
+
import uuid
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
import importlib.util
|
|
9
|
+
|
|
10
|
+
# Load `Log` directly from file to avoid importing package-level dependencies
|
|
11
|
+
repo_root = Path(__file__).resolve().parents[1]
|
|
12
|
+
log_path = repo_root / 'tir' / 'technologies' / 'core' / 'log.py'
|
|
13
|
+
spec = importlib.util.spec_from_file_location('tir_log', str(log_path))
|
|
14
|
+
mod = importlib.util.module_from_spec(spec)
|
|
15
|
+
|
|
16
|
+
# Inject minimal tir package stubs to avoid importing heavy dependencies during tests
|
|
17
|
+
import sys
|
|
18
|
+
pkg = types.ModuleType('tir')
|
|
19
|
+
sys.modules['tir'] = pkg
|
|
20
|
+
sys.modules['tir.technologies'] = types.ModuleType('tir.technologies')
|
|
21
|
+
sys.modules['tir.technologies.core'] = types.ModuleType('tir.technologies.core')
|
|
22
|
+
|
|
23
|
+
# Minimal ConfigLoader stub
|
|
24
|
+
cfg_mod = types.ModuleType('tir.technologies.core.config')
|
|
25
|
+
class DummyConfig:
|
|
26
|
+
def __init__(self, path=None):
|
|
27
|
+
self.issue = ''
|
|
28
|
+
self.execution_id = ''
|
|
29
|
+
self.country = 'BRA'
|
|
30
|
+
self.release = ''
|
|
31
|
+
self.logurl1 = ''
|
|
32
|
+
self.logurl2 = ''
|
|
33
|
+
self.smart_test = False
|
|
34
|
+
self.log_http = ''
|
|
35
|
+
self.num_exec = None
|
|
36
|
+
self.api_url = ''
|
|
37
|
+
self.api_url_ip = ''
|
|
38
|
+
self.api_json_path = str(repo_root / 'Log')
|
|
39
|
+
self.debug_log = False
|
|
40
|
+
cfg_mod.ConfigLoader = lambda path=None: DummyConfig(path)
|
|
41
|
+
sys.modules['tir.technologies.core.config'] = cfg_mod
|
|
42
|
+
|
|
43
|
+
# Minimal logging_config stub
|
|
44
|
+
logcfg_mod = types.ModuleType('tir.technologies.core.logging_config')
|
|
45
|
+
import logging
|
|
46
|
+
def logger():
|
|
47
|
+
return logging.getLogger('test_logger')
|
|
48
|
+
logcfg_mod.logger = logger
|
|
49
|
+
sys.modules['tir.technologies.core.logging_config'] = logcfg_mod
|
|
50
|
+
|
|
51
|
+
spec.loader.exec_module(mod)
|
|
52
|
+
Log = mod.Log
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def make_log_with_cfg(tmp_dir: Path):
|
|
56
|
+
l = Log(user='tester', station='station')
|
|
57
|
+
class Cfg:
|
|
58
|
+
pass
|
|
59
|
+
cfg = Cfg()
|
|
60
|
+
cfg.log_http = str(tmp_dir)
|
|
61
|
+
cfg.country = 'BRA'
|
|
62
|
+
cfg.release = '1.0'
|
|
63
|
+
cfg.issue = 'ISS'
|
|
64
|
+
cfg.execution_id = 'EID'
|
|
65
|
+
cfg.debug_log = False
|
|
66
|
+
l.config = cfg
|
|
67
|
+
return l
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_diagnostic_io_reports(tmp_path):
|
|
71
|
+
l = make_log_with_cfg(tmp_path)
|
|
72
|
+
res = l.diagnostic_io(tmp_path)
|
|
73
|
+
assert 'user' in res
|
|
74
|
+
assert 'target' in res
|
|
75
|
+
assert res['exists'] is True
|
|
76
|
+
assert isinstance(res['readable'], bool)
|
|
77
|
+
assert isinstance(res['writable'], bool)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_take_screenshot_writes_file(tmp_path):
|
|
81
|
+
l = make_log_with_cfg(tmp_path)
|
|
82
|
+
|
|
83
|
+
# Prepare a fake driver that actually writes the file so we can assert existence
|
|
84
|
+
captured = []
|
|
85
|
+
def save_screenshot(path):
|
|
86
|
+
captured.append(path)
|
|
87
|
+
Path(path).write_text('screenshot')
|
|
88
|
+
return True
|
|
89
|
+
|
|
90
|
+
driver = types.SimpleNamespace()
|
|
91
|
+
driver.save_screenshot = save_screenshot
|
|
92
|
+
|
|
93
|
+
screenshot_name = 'my_test'
|
|
94
|
+
stack_item = f"testcase_{uuid.uuid4().hex[:6]}"
|
|
95
|
+
|
|
96
|
+
l.take_screenshot_log(driver, description=screenshot_name, stack_item=stack_item)
|
|
97
|
+
|
|
98
|
+
testsuite = l.get_file_name("testsuite")
|
|
99
|
+
folder_path = Path(l.config.log_http, l.config.country, l.release, l.config.issue, l.config.execution_id, testsuite)
|
|
100
|
+
# Assert that driver was called and file was created at that path
|
|
101
|
+
assert captured, "Driver.save_screenshot was not called"
|
|
102
|
+
written_path = Path(captured[0])
|
|
103
|
+
assert written_path.exists()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_take_screenshot_fallback_on_write_fail(tmp_path, monkeypatch):
|
|
107
|
+
l = make_log_with_cfg(tmp_path)
|
|
108
|
+
|
|
109
|
+
# Simulate write failure (e.g., directory read-only)
|
|
110
|
+
def failing_save_screenshot(path):
|
|
111
|
+
raise PermissionError("Simulated write fail")
|
|
112
|
+
|
|
113
|
+
driver = types.SimpleNamespace()
|
|
114
|
+
driver.save_screenshot = failing_save_screenshot
|
|
115
|
+
|
|
116
|
+
# Monkeypatch tempfile.gettempdir to a controlled dir
|
|
117
|
+
temp_dir = tmp_path / 'fallback'
|
|
118
|
+
temp_dir.mkdir()
|
|
119
|
+
monkeypatch.setattr('tempfile.gettempdir', lambda: str(temp_dir))
|
|
120
|
+
|
|
121
|
+
# Should not crash; should log and continue
|
|
122
|
+
l.take_screenshot_log(driver, description='fail_test', stack_item='testcase_123')
|
|
123
|
+
# Verify if file was created in fallback (if applicable)
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"""Unit tests for Utils class and its methods."""
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
import unittest
|
|
7
|
+
from unittest.mock import MagicMock, patch
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
# Add the parent directory to the path so we can import tir module
|
|
11
|
+
repo_root = Path(__file__).resolve().parents[1]
|
|
12
|
+
sys.path.insert(0, str(repo_root))
|
|
13
|
+
|
|
14
|
+
from tir.technologies.core.utils import Utils
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TestUtilsGetMainEntrypointFromStack(unittest.TestCase):
|
|
18
|
+
"""Test cases for Utils.get_main_entrypoint_from_stack method."""
|
|
19
|
+
|
|
20
|
+
def setUp(self):
|
|
21
|
+
"""Initialize test fixtures."""
|
|
22
|
+
self.utils = Utils()
|
|
23
|
+
|
|
24
|
+
def test_get_main_entrypoint_with_default_parameters(self):
|
|
25
|
+
"""Test method returns a string value with default parameters."""
|
|
26
|
+
result = self.utils.get_main_entrypoint_from_stack()
|
|
27
|
+
self.assertIsInstance(result, str)
|
|
28
|
+
|
|
29
|
+
def test_get_main_entrypoint_returns_fallback_when_no_match(self):
|
|
30
|
+
"""Test method returns fallback value when no matching frame is found."""
|
|
31
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
32
|
+
target_modules=["nonexistent/module.py"],
|
|
33
|
+
fallback="custom_fallback"
|
|
34
|
+
)
|
|
35
|
+
self.assertEqual(result, "custom_fallback")
|
|
36
|
+
|
|
37
|
+
def test_get_main_entrypoint_returns_default_fallback(self):
|
|
38
|
+
"""Test method returns default fallback when no matching frame is found."""
|
|
39
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
40
|
+
target_modules=["nonexistent/module.py"]
|
|
41
|
+
)
|
|
42
|
+
self.assertEqual(result, "function_name")
|
|
43
|
+
|
|
44
|
+
def test_get_main_entrypoint_ignores_specified_functions(self):
|
|
45
|
+
"""Test that specified functions in ignored_functions are skipped."""
|
|
46
|
+
# Create a set of functions to ignore
|
|
47
|
+
ignored_set = {"__getattribute__", "_subscribe_routes", "__init__", "<lambda>"}
|
|
48
|
+
|
|
49
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
50
|
+
target_modules=["test_utils.py"],
|
|
51
|
+
ignored_functions=ignored_set,
|
|
52
|
+
fallback="test_fallback"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# The result should not be in the ignored set or should be fallback
|
|
56
|
+
if result != "test_fallback":
|
|
57
|
+
self.assertNotIn(result, ignored_set)
|
|
58
|
+
|
|
59
|
+
def test_get_main_entrypoint_with_custom_ignored_functions(self):
|
|
60
|
+
"""Test method with custom ignored functions set."""
|
|
61
|
+
custom_ignored = {"test_method", "setup"}
|
|
62
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
63
|
+
target_modules=["test_utils.py"],
|
|
64
|
+
ignored_functions=custom_ignored,
|
|
65
|
+
fallback="not_found"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
self.assertIsInstance(result, str)
|
|
69
|
+
|
|
70
|
+
def test_get_main_entrypoint_case_insensitive_matching(self):
|
|
71
|
+
"""Test that module matching is case-insensitive."""
|
|
72
|
+
# Test with uppercase module name
|
|
73
|
+
result1 = self.utils.get_main_entrypoint_from_stack(
|
|
74
|
+
target_modules=["TEST_UTILS.PY"],
|
|
75
|
+
fallback="not_found"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Test with lowercase module name
|
|
79
|
+
result2 = self.utils.get_main_entrypoint_from_stack(
|
|
80
|
+
target_modules=["test_utils.py"],
|
|
81
|
+
fallback="not_found"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Both should return the same result
|
|
85
|
+
self.assertEqual(result1, result2)
|
|
86
|
+
|
|
87
|
+
def test_get_main_entrypoint_with_path_separators(self):
|
|
88
|
+
"""Test that method handles both forward and backward slashes."""
|
|
89
|
+
# Test with forward slashes
|
|
90
|
+
result1 = self.utils.get_main_entrypoint_from_stack(
|
|
91
|
+
target_modules=["tests/test_utils.py"],
|
|
92
|
+
fallback="not_found"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Test with backward slashes (Windows style)
|
|
96
|
+
result2 = self.utils.get_main_entrypoint_from_stack(
|
|
97
|
+
target_modules=["tests\\test_utils.py"],
|
|
98
|
+
fallback="not_found"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Both should return the same result
|
|
102
|
+
self.assertEqual(result1, result2)
|
|
103
|
+
|
|
104
|
+
def test_get_main_entrypoint_multiple_target_modules(self):
|
|
105
|
+
"""Test method with multiple target modules."""
|
|
106
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
107
|
+
target_modules=["nonexistent.py", "test_utils.py", "another.py"],
|
|
108
|
+
fallback="not_found"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
self.assertIsInstance(result, str)
|
|
112
|
+
|
|
113
|
+
@patch('inspect.stack')
|
|
114
|
+
def test_get_main_entrypoint_with_mocked_stack(self, mock_stack):
|
|
115
|
+
"""Test method behavior with mocked call stack."""
|
|
116
|
+
# Create mock stack frames
|
|
117
|
+
mock_frame1 = MagicMock()
|
|
118
|
+
mock_frame1.filename = "c:\\TOTVS\\repos\\tir\\tir\\main.py"
|
|
119
|
+
mock_frame1.function = "test_function"
|
|
120
|
+
|
|
121
|
+
mock_frame2 = MagicMock()
|
|
122
|
+
mock_frame2.filename = "c:\\other\\path\\module.py"
|
|
123
|
+
mock_frame2.function = "other_function"
|
|
124
|
+
|
|
125
|
+
mock_stack.return_value = [mock_frame1, mock_frame2]
|
|
126
|
+
|
|
127
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
128
|
+
target_modules=["tir/main.py"]
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
self.assertEqual(result, "test_function")
|
|
132
|
+
|
|
133
|
+
@patch('inspect.stack')
|
|
134
|
+
def test_get_main_entrypoint_skips_ignored_functions(self, mock_stack):
|
|
135
|
+
"""Test that method skips frames with ignored functions."""
|
|
136
|
+
# Create mock stack frames
|
|
137
|
+
mock_frame1 = MagicMock()
|
|
138
|
+
mock_frame1.filename = "c:\\TOTVS\\repos\\tir\\tir\\main.py"
|
|
139
|
+
mock_frame1.function = "__init__" # This should be ignored
|
|
140
|
+
|
|
141
|
+
mock_frame2 = MagicMock()
|
|
142
|
+
mock_frame2.filename = "c:\\TOTVS\\repos\\tir\\tir\\main.py"
|
|
143
|
+
mock_frame2.function = "user_function" # This should be returned
|
|
144
|
+
|
|
145
|
+
mock_stack.return_value = [mock_frame1, mock_frame2]
|
|
146
|
+
|
|
147
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
148
|
+
target_modules=["tir/main.py"]
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
self.assertEqual(result, "user_function")
|
|
152
|
+
|
|
153
|
+
@patch('inspect.stack')
|
|
154
|
+
def test_get_main_entrypoint_returns_first_match(self, mock_stack):
|
|
155
|
+
"""Test that method returns the first matching function."""
|
|
156
|
+
# Create mock stack frames
|
|
157
|
+
mock_frame1 = MagicMock()
|
|
158
|
+
mock_frame1.filename = "c:\\TOTVS\\repos\\tir\\tir\\main.py"
|
|
159
|
+
mock_frame1.function = "first_function"
|
|
160
|
+
|
|
161
|
+
mock_frame2 = MagicMock()
|
|
162
|
+
mock_frame2.filename = "c:\\TOTVS\\repos\\tir\\tir\\main.py"
|
|
163
|
+
mock_frame2.function = "second_function"
|
|
164
|
+
|
|
165
|
+
mock_stack.return_value = [mock_frame1, mock_frame2]
|
|
166
|
+
|
|
167
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
168
|
+
target_modules=["tir/main.py"]
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Should return the first matching function
|
|
172
|
+
self.assertEqual(result, "first_function")
|
|
173
|
+
|
|
174
|
+
def test_get_main_entrypoint_empty_ignored_functions(self):
|
|
175
|
+
"""Test method with empty ignored functions set."""
|
|
176
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
177
|
+
target_modules=["test_utils.py"],
|
|
178
|
+
ignored_functions=set(),
|
|
179
|
+
fallback="fallback"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
self.assertIsInstance(result, str)
|
|
183
|
+
|
|
184
|
+
def test_get_main_entrypoint_returns_string_type(self):
|
|
185
|
+
"""Test that method always returns a string."""
|
|
186
|
+
test_cases = [
|
|
187
|
+
{"target_modules": None},
|
|
188
|
+
{"target_modules": ["nonexistent.py"]},
|
|
189
|
+
{"fallback": "custom"},
|
|
190
|
+
{"ignored_functions": set()},
|
|
191
|
+
]
|
|
192
|
+
|
|
193
|
+
for kwargs in test_cases:
|
|
194
|
+
result = self.utils.get_main_entrypoint_from_stack(**kwargs)
|
|
195
|
+
self.assertIsInstance(result, str,
|
|
196
|
+
f"Expected str, got {type(result)} for kwargs: {kwargs}")
|
|
197
|
+
|
|
198
|
+
def test_utils_instantiation(self):
|
|
199
|
+
"""Test that Utils class can be instantiated."""
|
|
200
|
+
utils_instance = Utils()
|
|
201
|
+
self.assertIsNotNone(utils_instance)
|
|
202
|
+
self.assertTrue(hasattr(utils_instance, 'get_main_entrypoint_from_stack'))
|
|
203
|
+
|
|
204
|
+
def test_get_main_entrypoint_with_absolute_path_module(self):
|
|
205
|
+
"""Test method with absolute path in target_modules."""
|
|
206
|
+
abs_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "test_utils.py"))
|
|
207
|
+
|
|
208
|
+
result = self.utils.get_main_entrypoint_from_stack(
|
|
209
|
+
target_modules=[abs_path],
|
|
210
|
+
fallback="not_found"
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
self.assertIsInstance(result, str)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class TestUtilsClass(unittest.TestCase):
|
|
217
|
+
"""Test cases for Utils class itself."""
|
|
218
|
+
|
|
219
|
+
def test_utils_has_get_main_entrypoint_method(self):
|
|
220
|
+
"""Test that Utils class has the get_main_entrypoint_from_stack method."""
|
|
221
|
+
utils = Utils()
|
|
222
|
+
self.assertTrue(hasattr(utils, 'get_main_entrypoint_from_stack'))
|
|
223
|
+
self.assertTrue(callable(getattr(utils, 'get_main_entrypoint_from_stack')))
|
|
224
|
+
|
|
225
|
+
def test_utils_docstring_exists(self):
|
|
226
|
+
"""Test that Utils class has proper documentation."""
|
|
227
|
+
self.assertIsNotNone(Utils.__doc__)
|
|
228
|
+
self.assertTrue(len(Utils.__doc__) > 0)
|
|
229
|
+
|
|
230
|
+
def test_get_main_entrypoint_docstring_exists(self):
|
|
231
|
+
"""Test that method has proper documentation."""
|
|
232
|
+
method = Utils.get_main_entrypoint_from_stack
|
|
233
|
+
self.assertIsNotNone(method.__doc__)
|
|
234
|
+
self.assertTrue(len(method.__doc__) > 0)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
if __name__ == '__main__':
|
|
238
|
+
unittest.main()
|