robotframework-mock 0.5.0__tar.gz → 0.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.
Files changed (16) hide show
  1. {robotframework_mock-0.5.0/src/robotframework_mock.egg-info → robotframework_mock-0.7.0}/PKG-INFO +32 -1
  2. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/README.md +31 -0
  3. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/setup.cfg +1 -1
  4. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/src/MockResource/__init__.py +49 -6
  5. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0/src/robotframework_mock.egg-info}/PKG-INFO +32 -1
  6. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/LICENSE +0 -0
  7. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/MANIFEST.in +0 -0
  8. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/pyproject.toml +0 -0
  9. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/setup.py +0 -0
  10. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/src/MockCoverage/__init__.py +0 -0
  11. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/src/MockLibrary/__init__.py +0 -0
  12. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/src/_mock_core/__init__.py +0 -0
  13. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/src/robotframework_mock.egg-info/SOURCES.txt +0 -0
  14. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/src/robotframework_mock.egg-info/dependency_links.txt +0 -0
  15. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/src/robotframework_mock.egg-info/requires.txt +0 -0
  16. {robotframework_mock-0.5.0 → robotframework_mock-0.7.0}/src/robotframework_mock.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotframework-mock
3
- Version: 0.5.0
3
+ Version: 0.7.0
4
4
  Summary: A Robot Framework library for mocking keywords in unit tests
5
5
  Home-page: https://github.com/olesz/robotframework-mock
6
6
  Author: Lajos Olah
@@ -320,6 +320,37 @@ Mock a keyword with a return value or side effect.
320
320
  MockDB.Mock Keyword query return_value=test_data
321
321
  ```
322
322
 
323
+ `return_value` may be any Python object, not only a string, so a keyword that
324
+ forwards a query result or a parsed response body can be mocked directly:
325
+
326
+ ```robot
327
+ ${rows}= Evaluate [['Europe/Budapest']]
328
+ MockRes.Mock Keyword Run Query return_value=${rows}
329
+ ```
330
+
331
+ ### Mocked keyword setup and teardown
332
+
333
+ `MockResource` replaces only a keyword's **body**. Its `[Setup]` and `[Teardown]`
334
+ still run, which keeps them observable — a test can assert that a teardown
335
+ released a lock, for instance.
336
+
337
+ That is a problem when the teardown cleans up state the replaced body would have
338
+ created, because it then fails on the mocked call. Suppress it per mock:
339
+
340
+ ```robot
341
+ # Init Client acquires a lock in its body and releases it in its teardown.
342
+ # Without the body there is no lock to release, so skip the teardown.
343
+ MockRes.Mock Keyword Init Client return_value=alias skip_teardown=${True}
344
+ MockRes.Mock Keyword Init Client return_value=alias skip_setup=${True}
345
+ ```
346
+
347
+ Both default to `False`, so existing tests are unaffected. `Reset Mocks`
348
+ restores a suppressed setup or teardown along with the body.
349
+
350
+ Prefer the default when the setup or teardown is part of the contract you are
351
+ testing, and skip it when it is an implementation detail of a keyword the test
352
+ is only standing in for.
353
+
323
354
  ### Reset Mocks
324
355
 
325
356
  Restore all mocked keywords to their original implementations.
@@ -296,6 +296,37 @@ Mock a keyword with a return value or side effect.
296
296
  MockDB.Mock Keyword query return_value=test_data
297
297
  ```
298
298
 
299
+ `return_value` may be any Python object, not only a string, so a keyword that
300
+ forwards a query result or a parsed response body can be mocked directly:
301
+
302
+ ```robot
303
+ ${rows}= Evaluate [['Europe/Budapest']]
304
+ MockRes.Mock Keyword Run Query return_value=${rows}
305
+ ```
306
+
307
+ ### Mocked keyword setup and teardown
308
+
309
+ `MockResource` replaces only a keyword's **body**. Its `[Setup]` and `[Teardown]`
310
+ still run, which keeps them observable — a test can assert that a teardown
311
+ released a lock, for instance.
312
+
313
+ That is a problem when the teardown cleans up state the replaced body would have
314
+ created, because it then fails on the mocked call. Suppress it per mock:
315
+
316
+ ```robot
317
+ # Init Client acquires a lock in its body and releases it in its teardown.
318
+ # Without the body there is no lock to release, so skip the teardown.
319
+ MockRes.Mock Keyword Init Client return_value=alias skip_teardown=${True}
320
+ MockRes.Mock Keyword Init Client return_value=alias skip_setup=${True}
321
+ ```
322
+
323
+ Both default to `False`, so existing tests are unaffected. `Reset Mocks`
324
+ restores a suppressed setup or teardown along with the body.
325
+
326
+ Prefer the default when the setup or teardown is part of the contract you are
327
+ testing, and skip it when it is an implementation detail of a keyword the test
328
+ is only standing in for.
329
+
299
330
  ### Reset Mocks
300
331
 
301
332
  Restore all mocked keywords to their original implementations.
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = robotframework-mock
3
- version = 0.5.0
3
+ version = 0.7.0
4
4
  author = Lajos Olah
5
5
  author_email = lajos.olah.jr@gmail.com
6
6
  description = A Robot Framework library for mocking keywords in unit tests
@@ -11,6 +11,13 @@ from robot.utils import split_from_equals
11
11
 
12
12
  from _mock_core import CallInspectionMixin
13
13
 
14
+ # Robot resolves the values of a RETURN statement as variable expressions, so a
15
+ # mocked return value cannot be embedded in one directly - anything that is not
16
+ # a string raises a TypeError. The value is therefore published under this name
17
+ # and the injected RETURN refers to it, which lets a mock return any Python
18
+ # object (a query result set, a parsed JSON body, a list of pods...).
19
+ RETURN_VARIABLE = '${__mock_resource_return__}'
20
+
14
21
 
15
22
  def _resolve_arguments(keyword_obj, data, context):
16
23
  """Split a keyword call's raw arguments into resolved args and kwargs.
@@ -67,6 +74,8 @@ class MockResource(CallInspectionMixin):
67
74
  self._source = source
68
75
  self._original_get_runner = Namespace.get_runner
69
76
  self._original_items = {}
77
+ self._original_setups = {}
78
+ self._original_teardowns = {}
70
79
  self._mocks = {}
71
80
  self._install_patch()
72
81
 
@@ -90,7 +99,11 @@ class MockResource(CallInspectionMixin):
90
99
  keyword_runner.keyword, data, context
91
100
  )
92
101
  mock_result = mock(*args, **kwargs)
93
- keyword_runner.keyword.body._items = [Return(values=[mock_result])] # pylint: disable=protected-access
102
+ # Test scope, so the value is visible to the keyword's own
103
+ # body even when the mocked keyword is called from inside
104
+ # another keyword rather than directly from the test.
105
+ context.variables.set_test(RETURN_VARIABLE, mock_result)
106
+ keyword_runner.keyword.body._items = [Return(values=[RETURN_VARIABLE])] # pylint: disable=protected-access
94
107
  return original_run(data, result, context, run)
95
108
  keyword_runner.run = patched_run
96
109
 
@@ -101,22 +114,37 @@ class MockResource(CallInspectionMixin):
101
114
  @keyword
102
115
  def mock_keyword(
103
116
  self, keyword_name: str,
104
- return_value: Any = None, side_effect: Callable = None
117
+ return_value: Any = None, side_effect: Callable = None,
118
+ skip_setup: bool = False, skip_teardown: bool = False
105
119
  ):
106
120
  """Mock a keyword from the resource file.
107
-
121
+
122
+ Only the keyword's body is replaced. Its ``[Setup]`` and ``[Teardown]``
123
+ still run by default, which keeps them observable - a test can assert
124
+ that a teardown released a lock, for example. Suppress them when the
125
+ mocked keyword's own setup or teardown is an implementation detail the
126
+ test should not depend on, typically because it cleans up state that the
127
+ replaced body would have created and therefore fails.
128
+
108
129
  Args:
109
130
  keyword_name: Name of the keyword to mock
110
- return_value: Value to return when the keyword is called
131
+ return_value: Value to return when the keyword is called. May be any
132
+ Python object.
111
133
  side_effect: Callable to execute instead of returning a value.
112
134
  Receives the call's resolved arguments, the same way a
113
135
  ``MockLibrary`` side effect does.
136
+ skip_setup: Do not run the keyword's ``[Setup]`` while mocked.
137
+ skip_teardown: Do not run the keyword's ``[Teardown]`` while mocked.
114
138
 
115
139
  Returns:
116
140
  The :class:`unittest.mock.Mock` backing the keyword.
117
141
 
142
+ Raises:
143
+ AttributeError: If the keyword is not found in the resource file.
144
+
118
145
  Example:
119
146
  | MockRes.Mock Keyword | My Keyword | return_value=test_data |
147
+ | MockRes.Mock Keyword | Init Client | skip_teardown=${True} |
120
148
  """
121
149
  keyword_runner = BuiltIn()._namespace.get_runner(keyword_name, True) # pylint: disable=protected-access
122
150
  resource_file = getattr(keyword_runner.keyword, "source", None)
@@ -125,6 +153,12 @@ class MockResource(CallInspectionMixin):
125
153
  raise AttributeError("fKeyword '{keyword_name}' not found in {self._source}")
126
154
 
127
155
  self._original_items[keyword_name] = keyword_runner.keyword.body._items # pylint: disable=protected-access
156
+ if skip_setup:
157
+ self._original_setups[keyword_name] = keyword_runner.keyword.setup
158
+ keyword_runner.keyword.setup = None
159
+ if skip_teardown:
160
+ self._original_teardowns[keyword_name] = keyword_runner.keyword.teardown
161
+ keyword_runner.keyword.teardown = None
128
162
  mock = Mock(return_value=return_value, side_effect=side_effect)
129
163
  self._mocks[keyword_name] = mock
130
164
  return mock
@@ -133,8 +167,9 @@ class MockResource(CallInspectionMixin):
133
167
  def reset_mocks(self):
134
168
  """Reset all mocks to their original implementations.
135
169
 
136
- Restores all mocked keywords to their original behavior.
137
-
170
+ Restores all mocked keywords to their original behavior, including any
171
+ ``[Setup]`` or ``[Teardown]`` that was suppressed while mocked.
172
+
138
173
  Example:
139
174
  | MockRes.Reset Mocks |
140
175
  """
@@ -142,7 +177,15 @@ class MockResource(CallInspectionMixin):
142
177
  for keyword_name, items in self._original_items.items():
143
178
  keyword_runner = BuiltIn()._namespace.get_runner(keyword_name, True) # pylint: disable=protected-access
144
179
  keyword_runner.keyword.body._items = items # pylint: disable=protected-access
180
+ for keyword_name, setup in self._original_setups.items():
181
+ keyword_runner = BuiltIn()._namespace.get_runner(keyword_name, True) # pylint: disable=protected-access
182
+ keyword_runner.keyword.setup = setup
183
+ for keyword_name, teardown in self._original_teardowns.items():
184
+ keyword_runner = BuiltIn()._namespace.get_runner(keyword_name, True) # pylint: disable=protected-access
185
+ keyword_runner.keyword.teardown = teardown
145
186
  self._original_items.clear()
187
+ self._original_setups.clear()
188
+ self._original_teardowns.clear()
146
189
 
147
190
  @keyword
148
191
  def verify_keyword_called(self, keyword_name: str, times: int = None):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotframework-mock
3
- Version: 0.5.0
3
+ Version: 0.7.0
4
4
  Summary: A Robot Framework library for mocking keywords in unit tests
5
5
  Home-page: https://github.com/olesz/robotframework-mock
6
6
  Author: Lajos Olah
@@ -320,6 +320,37 @@ Mock a keyword with a return value or side effect.
320
320
  MockDB.Mock Keyword query return_value=test_data
321
321
  ```
322
322
 
323
+ `return_value` may be any Python object, not only a string, so a keyword that
324
+ forwards a query result or a parsed response body can be mocked directly:
325
+
326
+ ```robot
327
+ ${rows}= Evaluate [['Europe/Budapest']]
328
+ MockRes.Mock Keyword Run Query return_value=${rows}
329
+ ```
330
+
331
+ ### Mocked keyword setup and teardown
332
+
333
+ `MockResource` replaces only a keyword's **body**. Its `[Setup]` and `[Teardown]`
334
+ still run, which keeps them observable — a test can assert that a teardown
335
+ released a lock, for instance.
336
+
337
+ That is a problem when the teardown cleans up state the replaced body would have
338
+ created, because it then fails on the mocked call. Suppress it per mock:
339
+
340
+ ```robot
341
+ # Init Client acquires a lock in its body and releases it in its teardown.
342
+ # Without the body there is no lock to release, so skip the teardown.
343
+ MockRes.Mock Keyword Init Client return_value=alias skip_teardown=${True}
344
+ MockRes.Mock Keyword Init Client return_value=alias skip_setup=${True}
345
+ ```
346
+
347
+ Both default to `False`, so existing tests are unaffected. `Reset Mocks`
348
+ restores a suppressed setup or teardown along with the body.
349
+
350
+ Prefer the default when the setup or teardown is part of the contract you are
351
+ testing, and skip it when it is an implementation detail of a keyword the test
352
+ is only standing in for.
353
+
323
354
  ### Reset Mocks
324
355
 
325
356
  Restore all mocked keywords to their original implementations.