robotframework-pabot 5.0.0__py3-none-any.whl → 5.2.0b1__py3-none-any.whl

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.
pabot/pabotlib.py CHANGED
@@ -60,7 +60,7 @@ class _PabotLib(object):
60
60
  self, resourcefile
61
61
  ): # type: (Optional[str]) -> Dict[str, Dict[str, Any]]
62
62
  vals = {} # type: Dict[str, Dict[str, Any]]
63
- if resourcefile is None:
63
+ if not resourcefile:
64
64
  return vals
65
65
  conf = configparser.ConfigParser()
66
66
  conf.read(resourcefile)
pabot/result_merger.py CHANGED
@@ -201,13 +201,13 @@ def prefix(source, timestamp_id):
201
201
  if not id:
202
202
  return ""
203
203
  if os.path.split(path_without_id)[1] == 'pabot_results':
204
- return "-".join([timestamp_id, id])
204
+ return "-".join([str(p) for p in [timestamp_id, id] if p is not None])
205
205
  else:
206
206
  # --argumentfileN in use: (there should be one subdir level more)
207
207
  _, index = os.path.split(path_without_id)
208
208
  if not index:
209
209
  return ""
210
- return "-".join([timestamp_id, index, id])
210
+ return "-".join([str(p) for p in [timestamp_id, index, id] if p is not None])
211
211
  except:
212
212
  return ""
213
213
 
@@ -452,20 +452,28 @@ class StandardStreamInterceptor(object):
452
452
  self.output = ""
453
453
  self.origout = sys.stdout
454
454
  self.origerr = sys.stderr
455
- sys.stdout = StringIO()
456
- sys.stderr = StringIO()
455
+ self.stdout_capture = StringIO()
456
+ self.stderr_capture = StringIO()
457
+ sys.stdout = self.stdout_capture
458
+ sys.stderr = self.stderr_capture
457
459
 
458
460
  def __enter__(self):
459
461
  return self
460
462
 
461
463
  def __exit__(self, *exc_info):
462
- stdout = sys.stdout.getvalue()
463
- stderr = sys.stderr.getvalue()
464
- close = [sys.stdout, sys.stderr]
464
+ # Safely get output from captured streams, handling case where streams were restored
465
+ stdout = self._safe_getvalue(sys.stdout, self.stdout_capture)
466
+ stderr = self._safe_getvalue(sys.stderr, self.stderr_capture)
467
+
468
+ # Close only our StringIO objects
469
+ for stream in [self.stdout_capture, self.stderr_capture]:
470
+ if hasattr(stream, 'close'):
471
+ stream.close()
472
+
473
+ # Restore original streams
465
474
  sys.stdout = self.origout
466
475
  sys.stderr = self.origerr
467
- for stream in close:
468
- stream.close()
476
+
469
477
  if stdout and stderr:
470
478
  if not stderr.startswith(
471
479
  ("*TRACE*", "*DEBUG*", "*INFO*", "*HTML*", "*WARN*", "*ERROR*")
@@ -474,6 +482,18 @@ class StandardStreamInterceptor(object):
474
482
  if not stdout.endswith("\n"):
475
483
  stdout += "\n"
476
484
  self.output = stdout + stderr
485
+
486
+ def _safe_getvalue(self, current_stream, original_capture):
487
+ """Safely get value from stream, handling case where stream was restored."""
488
+ # If current stream is still our StringIO, get value from it
489
+ if hasattr(current_stream, 'getvalue') and current_stream is original_capture:
490
+ return current_stream.getvalue()
491
+ # If current stream was restored but our capture still has data
492
+ print("*WARN* Stream capture was interrupted", file=sys.stderr)
493
+ if hasattr(original_capture, 'getvalue'):
494
+ return original_capture.getvalue()
495
+ else:
496
+ return ""
477
497
 
478
498
 
479
499
  class KeywordResult(object):
pabot/skip_listener.py ADDED
@@ -0,0 +1,7 @@
1
+ ROBOT_LISTENER_API_VERSION = 3
2
+
3
+ def end_test(data, result):
4
+ # data: TestCase object
5
+ # result: TestCaseResult object
6
+ result.status = 'SKIP'
7
+ result.message = "Pabot skip logic: this test was skipped due to dependencies and failure policy."
@@ -0,0 +1,5 @@
1
+ ROBOT_LISTENER_API_VERSION = 3
2
+
3
+ def end_test(data, result):
4
+ result.status = 'FAIL'
5
+ result.message = "Pabot's --processtimeout option has been reached."
pabot/writer.py ADDED
@@ -0,0 +1,110 @@
1
+ import threading
2
+ import queue
3
+ import sys
4
+ import os
5
+ import time
6
+
7
+ class Color:
8
+ RED = "\033[91m"
9
+ GREEN = "\033[92m"
10
+ YELLOW = "\033[93m"
11
+ ENDC = "\033[0m"
12
+ SUPPORTED_OSES = {"posix"} # Only Unix terminals support ANSI colors
13
+
14
+
15
+ class MessageWriter:
16
+ def __init__(self, log_file=None):
17
+ self.queue = queue.Queue()
18
+ self.log_file = log_file
19
+ if log_file:
20
+ os.makedirs(os.path.dirname(log_file), exist_ok=True)
21
+ self._stop_event = threading.Event()
22
+ self.thread = threading.Thread(target=self._writer)
23
+ self.thread.daemon = True
24
+ self.thread.start()
25
+
26
+ def _is_output_coloring_supported(self):
27
+ return sys.stdout.isatty() and os.name in Color.SUPPORTED_OSES
28
+
29
+ def _wrap_with(self, color, message):
30
+ if self._is_output_coloring_supported() and color:
31
+ return f"{color}{message}{Color.ENDC}"
32
+ return message
33
+
34
+ def _writer(self):
35
+ while not self._stop_event.is_set():
36
+ try:
37
+ message, color = self.queue.get(timeout=0.1)
38
+ except queue.Empty:
39
+ continue
40
+ if message is None:
41
+ self.queue.task_done()
42
+ break
43
+ print(self._wrap_with(color, message))
44
+ sys.stdout.flush()
45
+ if self.log_file:
46
+ with open(self.log_file, "a", encoding="utf-8") as f:
47
+ f.write(message + "\n")
48
+ self.queue.task_done()
49
+
50
+ def write(self, message, color=None):
51
+ self.queue.put((f"{message}", color))
52
+
53
+ def flush(self, timeout=5):
54
+ """
55
+ Wait until all queued messages have been written.
56
+
57
+ :param timeout: Optional timeout in seconds. If None, wait indefinitely.
58
+ :return: True if queue drained before timeout (or no timeout), False if timed out.
59
+ """
60
+ start = time.time()
61
+ try:
62
+ # Loop until Queue reports no unfinished tasks
63
+ while True:
64
+ # If writer thread died, break to avoid infinite loop
65
+ if not self.thread.is_alive():
66
+ # Give one last moment for potential in-flight task_done()
67
+ time.sleep(0.01)
68
+ # If still unfinished, we can't do more
69
+ return getattr(self.queue, "unfinished_tasks", 0) == 0
70
+
71
+ unfinished = getattr(self.queue, "unfinished_tasks", None)
72
+ if unfinished is None:
73
+ # Fallback: call join once and return
74
+ try:
75
+ self.queue.join()
76
+ return True
77
+ except Exception:
78
+ return False
79
+
80
+ if unfinished == 0:
81
+ return True
82
+
83
+ if timeout is not None and (time.time() - start) > timeout:
84
+ return False
85
+
86
+ time.sleep(0.05)
87
+ except KeyboardInterrupt:
88
+ # Allow tests/cli to interrupt flushing
89
+ return False
90
+
91
+ def stop(self):
92
+ """
93
+ Gracefully stop the writer thread and flush remaining messages.
94
+ """
95
+ self.flush()
96
+ self._stop_event.set()
97
+ self.queue.put((None, None)) # sentinel to break thread loop
98
+ self.thread.join(timeout=1.0)
99
+
100
+
101
+ _writer_instance = None
102
+
103
+ def get_writer(log_dir=None):
104
+ global _writer_instance
105
+ if _writer_instance is None:
106
+ if log_dir:
107
+ os.makedirs(log_dir, exist_ok=True)
108
+ log_file = os.path.join(log_dir or ".", "pabot_manager.log")
109
+ _writer_instance = MessageWriter(log_file=log_file)
110
+ return _writer_instance
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotframework-pabot
3
- Version: 5.0.0
3
+ Version: 5.2.0b1
4
4
  Summary: Parallel test runner for Robot Framework
5
5
  Home-page: https://pabot.org
6
6
  Download-URL: https://pypi.python.org/pypi/robotframework-pabot
@@ -12,17 +12,14 @@ Classifier: Intended Audience :: Developers
12
12
  Classifier: Natural Language :: English
13
13
  Classifier: Programming Language :: Python :: 3
14
14
  Classifier: Topic :: Software Development :: Testing
15
- Classifier: License :: OSI Approved :: Apache Software License
16
15
  Classifier: Development Status :: 5 - Production/Stable
17
16
  Classifier: Framework :: Robot Framework
18
17
  Requires-Python: >=3.6
19
18
  Description-Content-Type: text/markdown
20
- License-File: LICENSE.txt
21
19
  Requires-Dist: robotframework>=3.2
22
20
  Requires-Dist: robotframework-stacktrace>=0.4.1
23
21
  Requires-Dist: natsort>=8.2.0
24
22
  Dynamic: download-url
25
- Dynamic: license-file
26
23
 
27
24
  # Pabot
28
25
 
@@ -47,7 +44,7 @@ A parallel executor for [Robot Framework](http://www.robotframework.org) tests.
47
44
  - [Contributing](#contributing-to-the-project)
48
45
  - [Command-line options](#command-line-options)
49
46
  - [PabotLib](#pabotlib)
50
- - [Controlling execution order](#controlling-execution-order-and-level-of-parallelism)
47
+ - [Controlling execution order, mode and level of parallelism](#controlling-execution-order-mode-and-level-of-parallelism)
51
48
  - [Programmatic use](#programmatic-use)
52
49
  - [Global variables](#global-variables)
53
50
  - [Output Files Generated by Pabot](#output-files-generated-by-pabot)
@@ -98,65 +95,89 @@ There are several ways you can help in improving this tool:
98
95
  - Report an issue or an improvement idea to the [issue tracker](https://github.com/mkorpela/pabot/issues)
99
96
  - Contribute by programming and making a pull request (easiest way is to work on an issue from the issue tracker)
100
97
 
98
+ Before contributing, please read our detailed contributing guidelines:
99
+
100
+ - [Contributing Guide](CONTRIBUTING.md)
101
+ - [Code of Conduct](CODE_OF_CONDUCT.md)
102
+ - [Security Policy](SECURITY.md)
103
+
101
104
  ## Command-line options
105
+ <!-- NOTE:
106
+ The sections inside these docstring markers are also used in Pabot's --help output.
107
+ Currently, the following transformations are applied:
108
+ - Remove Markdown links but keep the text
109
+ - Remove ** and backticks `
110
+
111
+ If you modify this part, make sure the Markdown section still looks clean and readable in the --help output. -->
112
+
102
113
  <!-- START DOCSTRING -->
114
+ ```
103
115
  pabot [--verbose|--testlevelsplit|--command .. --end-command|
104
116
  --processes num|--no-pabotlib|--pabotlibhost host|--pabotlibport port|
105
117
  --processtimeout num|
106
118
  --shard i/n|
107
119
  --artifacts extensions|--artifactsinsubfolders|
108
- --resourcefile file|--argumentfile[num] file|--suitesfrom file|--ordering file|
120
+ --resourcefile file|--argumentfile[num] file|--suitesfrom file
121
+ --ordering <FILENAME> [static|dynamic] [skip|run_all]|
109
122
  --chunk|
110
123
  --pabotprerunmodifier modifier|
111
124
  --no-rebot|
112
125
  --help|--version]
113
126
  [robot options] [path ...]
127
+ ```
114
128
 
115
129
  PabotLib remote server is started by default to enable locking and resource distribution between parallel test executions.
116
130
 
117
- Supports all [Robot Framework command line options](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#all-command-line-options) and also following pabot options:
131
+ Supports all [Robot Framework command line options](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#command-line-options) and also following pabot options:
118
132
 
119
- --verbose
133
+ **--verbose**
120
134
  More output from the parallel execution.
121
135
 
122
- --testlevelsplit
136
+ **--testlevelsplit**
123
137
  Split execution on test level instead of default suite level. If .pabotsuitenames contains both tests and suites then
124
138
  this will only affect new suites and split only them. Leaving this flag out when both suites and tests in
125
139
  .pabotsuitenames file will also only affect new suites and add them as suite files.
126
140
 
127
- --command [ACTUAL COMMANDS TO START ROBOT EXECUTOR] --end-command
141
+ **--command [ACTUAL COMMANDS TO START ROBOT EXECUTOR] --end-command**
128
142
  RF script for situations where robot is not used directly.
129
143
 
130
- --processes [NUMBER OF PROCESSES]
144
+ **--processes [NUMBER OF PROCESSES]**
131
145
  How many parallel executors to use (default max of 2 and cpu count). Special option "all" will use as many processes as
132
146
  there are executable suites or tests.
133
147
 
134
- --no-pabotlib
148
+ **--no-pabotlib**
135
149
  Disable the PabotLib remote server if you don't need locking or resource distribution features.
136
150
 
137
- --pabotlibhost [HOSTNAME]
151
+ **--pabotlibhost [HOSTNAME]**
138
152
  Connect to an already running instance of the PabotLib remote server at the given host (disables the local PabotLib
139
153
  server start). For example, to connect to a remote PabotLib server running on another machine:
140
154
 
141
155
  pabot --pabotlibhost 192.168.1.123 --pabotlibport 8271 tests/
142
156
 
143
- The remote server can be also started and executed separately from pabot instances:
157
+ The remote server can also be started and executed separately from pabot instances:
144
158
 
145
159
  python -m pabot.pabotlib <path_to_resourcefile> <host> <port>
146
160
  python -m pabot.pabotlib resource.txt 192.168.1.123 8271
147
161
 
148
162
  This enables sharing a resource with multiple Robot Framework instances.
149
163
 
150
- --pabotlibport [PORT]
164
+ Additional details:
165
+ - The default value for --pabotlibhost is 127.0.0.1.
166
+ - If you provide a hostname other than 127.0.0.1, the local PabotLib server startup is automatically disabled.
167
+
168
+ **--pabotlibport [PORT]**
151
169
  Port number of the PabotLib remote server (default is 8270). See --pabotlibhost for more information.
152
170
 
153
- --processtimeout [TIMEOUT]
171
+ Behavior with port and host settings:
172
+ - If you set the port value to 0 and --pabotlibhost is 127.0.0.1 (default), a free port on localhost will be assigned automatically.
173
+
174
+ **--processtimeout [TIMEOUT]**
154
175
  Maximum time in seconds to wait for a process before killing it. If not set, there's no timeout.
155
176
 
156
- --shard [INDEX]/[TOTAL]
177
+ **--shard [INDEX]/[TOTAL]**
157
178
  Optionally split execution into smaller pieces. This can be used for distributing testing to multiple machines.
158
179
 
159
- --artifacts [FILE EXTENSIONS]
180
+ **--artifacts [FILE EXTENSIONS]**
160
181
  List of file extensions (comma separated). Defines which files (screenshots, videos etc.) from separate reporting
161
182
  directories would be copied and included in a final report. Possible links to copied files in RF log would be updated
162
183
  (only relative paths supported). The default value is `png`.
@@ -165,49 +186,53 @@ Supports all [Robot Framework command line options](https://robotframework.org/r
165
186
 
166
187
  --artifacts png,mp4,txt
167
188
 
168
- --artifactsinsubfolders
189
+ The artifact naming conventions are described in the README.md section: [Output Files Generated by Pabot](#output-files-generated-by-pabot).
190
+
191
+ **--artifactsinsubfolders**
169
192
  Copy artifacts located not only directly in the RF output dir, but also in it's sub-folders.
170
193
 
171
- --resourcefile [FILEPATH]
194
+ **--resourcefile [FILEPATH]**
172
195
  Indicator for a file that can contain shared variables for distributing resources. This needs to be used together with
173
196
  pabotlib option. Resource file syntax is same as Windows ini files. Where a section is a shared set of variables.
174
197
 
175
- --argumentfile[INTEGER] [FILEPATH]
198
+ **--argumentfile[INTEGER] [FILEPATH]**
176
199
  Run same suites with multiple [argumentfile](http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#argument-files) options.
177
200
 
178
201
  For example:
179
202
 
180
203
  --argumentfile1 arg1.txt --argumentfile2 arg2.txt
181
204
 
182
- --suitesfrom [FILEPATH TO OUTPUTXML]
205
+ **--suitesfrom [FILEPATH TO OUTPUTXML]**
183
206
  Optionally read suites from output.xml file. Failed suites will run first and longer running ones will be executed
184
207
  before shorter ones.
185
208
 
186
- --ordering [FILE PATH]
187
- Optionally give execution order from a file.
209
+ **--ordering [FILE PATH] [MODE] [FAILURE POLICY]**
210
+ Optionally give execution order from a file. See README.md section: [Controlling execution order, mode and level of parallelism](#controlling-execution-order-mode-and-level-of-parallelism)
211
+ - MODE (optional): [static (default)|dynamic]
212
+ - FAILURE POLICY (optional, only in dynamic mode): [skip|run_all (default)]
188
213
 
189
- --chunk
214
+ **--chunk**
190
215
  Optionally chunk tests to PROCESSES number of robot runs. This can save time because all the suites will share the same
191
216
  setups and teardowns.
192
217
 
193
- --pabotprerunmodifier [PRERUNMODIFIER MODULE OR CLASS]
218
+ **--pabotprerunmodifier [PRERUNMODIFIER MODULE OR CLASS]**
194
219
  Like Robot Framework's --prerunmodifier, but executed only once in the pabot's main process after all other
195
220
  --prerunmodifiers. But unlike the regular --prerunmodifier command, --pabotprerunmodifier is not executed again in each
196
221
  pabot subprocesses. Depending on the intended use, this may be desirable as well as more efficient. Can be used, for
197
222
  example, to modify the list of tests to be performed.
198
223
 
199
- --no-rebot
224
+ **--no-rebot**
200
225
  If specified, the tests will execute as usual, but Rebot will not be called to merge the logs. This option is designed
201
226
  for scenarios where Rebot should be run later due to large log files, ensuring better memory and resource availability.
202
227
  Subprocess results are stored in the pabot_results folder.
203
228
 
204
- --help
229
+ **--help**
205
230
  Print usage instructions.
206
231
 
207
- --version
232
+ **--version**
208
233
  Print version information.
209
234
 
210
- Example usages:
235
+ **Example usages:**
211
236
 
212
237
  pabot test_directory
213
238
  pabot --exclude FOO directory_to_tests
@@ -226,6 +251,9 @@ These can be helpful when you must ensure that only one of the processes uses so
226
251
 
227
252
  PabotLib Docs are located at https://pabot.org/PabotLib.html.
228
253
 
254
+ Note that PabotLib uses the XML-RPC protocol, which does not support all possible object types.
255
+ These limitations are described in the Robot Framework documentation in chapter [Supported argument and return value types](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#supported-argument-and-return-value-types).
256
+
229
257
  ### PabotLib example:
230
258
 
231
259
  test.robot
@@ -271,18 +299,28 @@ pabot call using resources from valueset.dat
271
299
 
272
300
  pabot --pabotlib --resourcefile valueset.dat test.robot
273
301
 
274
- ### Controlling execution order and level of parallelism
302
+ ### Controlling execution order, mode, and level of parallelism
275
303
 
276
304
  .pabotsuitenames file contains the list of suites that will be executed.
277
- File is created during pabot execution if not already there.
278
- The file is a cache that pabot uses when re-executing same tests to speed up processing.
279
- This file can be partially manually edited but easier option is to use ```--ordering FILENAME```.
280
- First 4 rows contain information that should not be edited - pabot will edit these when something changes.
281
- After this come the suite names.
305
+ This file is created during pabot execution if it does not already exist. It acts as a cache to speed up processing when re-executing the same tests.
306
+ The file can be manually edited partially, but a simpler and more controlled approach is to use:
307
+
308
+ ```bash
309
+ --ordering <FILENAME> [static|dynamic] [skip|run_all]
310
+ ```
311
+
312
+ - **FILENAME** – path to the ordering file.
313
+ - **mode** – optional execution mode, either `static` (default) or `dynamic`.
314
+ - `static` executes suites in predefined stages.
315
+ - `dynamic` executes tests as soon as all their dependencies are satisfied, allowing more optimal parallel execution.
316
+ - **failure_policy** – determines behavior when dependencies fail. Used only in dynamic mode. Optional:
317
+ - `skip` – dependent tests are skipped if a dependency fails.
318
+ - `run_all` – all tests run regardless of failures (default).
282
319
 
283
- With ```--ordering FILENAME``` you can have a list that controls order also. The syntax is same as .pabotsuitenames file syntax but does not contain 4 hash rows that are present in .pabotsuitenames.
320
+ The ordering file syntax is similar to `.pabotsuitenames` but does not include the first 4 hash rows used by pabot. The ordering file defines the **execution order and dependencies** of suites and tests.
321
+ The actual selection of what to run must still be done using options like `--test`, `--suite`, `--include`, or `--exclude`.
284
322
 
285
- Note: The `--ordering` file is intended only for defining the execution order of suites and tests. The actual selection of what to run must still be done using options like `--test`, `--suite`, `--include`, or `--exclude`.
323
+ #### Controlling execution order
286
324
 
287
325
  There different possibilities to influence the execution:
288
326
 
@@ -294,7 +332,7 @@ There different possibilities to influence the execution:
294
332
  --suite Top Suite
295
333
  ```
296
334
 
297
- * If the base suite name is changing with robot option [```--name / -N```](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#setting-the-name) you can use either the new or old full test path. For example:
335
+ * If the base suite name is changing with robot option [```--name / -N```](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#setting-suite-name) you can use either the new or old full test path. For example:
298
336
 
299
337
  ```
300
338
  --test New Suite Name.Sub Suite.Test 1
@@ -304,8 +342,14 @@ OR
304
342
 
305
343
  * You can add a line with text `#WAIT` to force executor to wait until all previous suites have been executed.
306
344
  * You can group suites and tests together to same executor process by adding line `{` before the group and `}` after. Note that `#WAIT` cannot be used inside a group.
307
- * You can introduce dependencies using the word `#DEPENDS` after a test declaration. This keyword can be used several times if it is necessary to refer to several different tests. The ordering algorithm is designed to preserve the exact user-defined order as closely as possible. However, if a test's execution dependencies are not yet satisfied, the test is postponed and moved to the earliest possible stage where all its dependencies are fulfilled. Please take care that in case of circular dependencies an exception will be thrown. Note that each `#WAIT` splits suites into separate execution blocks, and it's not possible to define dependencies for suites or tests that are inside another `#WAIT` block or inside another `{}` braces.
308
- * Note: Within a group `{}`, neither execution order nor the `#DEPENDS` keyword currently works. This is due to limitations in Robot Framework, which is invoked within Pabot subprocesses. These limitations may be addressed in a future release of Robot Framework. For now, tests or suites within a group will be executed in the order Robot Framework discovers them typically in alphabetical order.
345
+ * You can introduce dependencies using the word `#DEPENDS` after a test declaration. This keyword can be used several times if it is necessary to refer to several different tests.
346
+ * The ordering algorithm is designed to preserve the exact user-defined order as closely as possible. However, if a test's execution dependencies are not yet satisfied, the test is postponed and moved to the earliest possible stage where all its dependencies are fulfilled.
347
+ * Please take care that in case of circular dependencies an exception will be thrown.
348
+ * Note that each `#WAIT` splits suites into separate execution blocks, and it's not possible to define dependencies for suites or tests that are inside another `#WAIT` block or inside another `{}` braces.
349
+ * Ordering mode effect to execution:
350
+ * **Dynamic mode** will schedule dependent tests as soon as all their dependencies are satisfied. Note that in dynamic mode `#WAIT` is ignored, but you can achieve same results with using only `#DEPENDS` keywords.
351
+ * **Static mode** preserves stage barriers and executes the next stage only after all tests in the previous stage finish.
352
+ * Note: Within a group `{}`, neither execution order nor the `#DEPENDS` keyword currently works. This is due to limitations in Robot Framework, which is invoked within Pabot subprocesses. These limitations may be addressed in a future release of Robot Framework. For now, tests or suites within a group will be executed in the order Robot Framework discovers them — typically in alphabetical order.
309
353
  * An example could be:
310
354
 
311
355
  ```
@@ -359,7 +403,7 @@ where order.txt is:
359
403
  #SLEEP 8
360
404
  ```
361
405
 
362
- prints something like this:
406
+ Possible output could be:
363
407
 
364
408
  ```
365
409
  2025-02-15 19:15:00.408321 [0] [ID:1] SLEEPING 6 SECONDS BEFORE STARTING Data 1.suite C
@@ -424,6 +468,12 @@ Artifacts are **copied** into the output directory and renamed with the followin
424
468
  TIMESTAMP-ARGUMENT_INDEX-PABOTQUEUEINDEX
425
469
  ```
426
470
 
471
+ If you use the special option `notimestamps` at the end of the `--artifacts` command, (For example: `--artifacts png,txt,notimestamps`) the timestamp part will be omitted, and the name will be in the format:
472
+
473
+ ```
474
+ ARGUMENT_INDEX-PABOTQUEUEINDEX
475
+ ```
476
+
427
477
  - **TIMESTAMP** = Time of `pabot` command invocation (not the screenshot's actual timestamp), format: `YYYYmmdd_HHMMSS`
428
478
  - **ARGUMENT_INDEX** = Optional index number, only used if `--argumentfileN` options are given
429
479
  - **PABOTQUEUEINDEX** = Process queue index (see section [Global Variables](#global-variables))
@@ -441,6 +491,7 @@ pabot_results/
441
491
  │ ├── robot_stdout.out
442
492
  │ ├── robot_stderr.out
443
493
  │ └── artifacts...
494
+ pabot_manager.log # Pabot's own main log. Basically same than prints in console
444
495
  ```
445
496
 
446
497
  Each `PABOTQUEUEINDEX` folder contains as default:
@@ -0,0 +1,25 @@
1
+ pabot/ProcessManager.py,sha256=w3dgtEKGhn4rj3nQ1EEQFAPeiIv6OF-KU6R3WZwQxPs,11739
2
+ pabot/SharedLibrary.py,sha256=mIipGs3ZhKYEakKprcbrMI4P_Un6qI8gE7086xpHaLY,2552
3
+ pabot/__init__.py,sha256=KuCXsD2BDgEFiQAxVRLN3SXkkyCULXtW06tTTqCEuRo,202
4
+ pabot/arguments.py,sha256=6MBXKnbDgWNdu7NnRqqd2_GNOs-u8QOxCz9wHhyfUVI,11404
5
+ pabot/clientwrapper.py,sha256=yz7battGs0exysnDeLDWJuzpb2Q-qSjitwxZMO2TlJw,231
6
+ pabot/coordinatorwrapper.py,sha256=nQQ7IowD6c246y8y9nsx0HZbt8vS2XODhPVDjm-lyi0,195
7
+ pabot/execution_items.py,sha256=zDVGW0AAeVbM-scC3Yui2TxvIPx1wYyFKHTPU2BkJkY,13329
8
+ pabot/pabot.py,sha256=hfMZdMYmeZEo3mNAVrvmuPU9vGhKpIBEVq5R8BI5ovE,87438
9
+ pabot/pabotlib.py,sha256=vHbqV7L7mIvDzXBh9UcdULrwhBHNn70EDXF_31MNFO4,22320
10
+ pabot/result_merger.py,sha256=g4mm-BhhMK57Z6j6dpvfL5El1g5onOtfV4RByNrO8g0,9744
11
+ pabot/robotremoteserver.py,sha256=BdeIni9Q4LJKVDBUlG2uJ9tiyAjrPXwU_YsPq1THWoo,23296
12
+ pabot/skip_listener.py,sha256=xv7wH-yB_nfc_AT1oZh3C0iu8hS67g5a28x8hwSrYsE,254
13
+ pabot/timeout_listener.py,sha256=twZFiJEyn9tAqI1K6JDBGaZrxRqVLFDVWvyxa6d8Lb0,160
14
+ pabot/workerwrapper.py,sha256=BdELUVDs5BmEkdNBcYTlnP22Cj0tUpZEunYQMAKyKWU,185
15
+ pabot/writer.py,sha256=_sRN_EqIhaMwPYmTkN4NzO2Mj6tggcaxgYkqJKatb_c,3639
16
+ pabot/py3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ pabot/py3/client.py,sha256=Od9L4vZ0sozMHq_W_ITQHBBt8kAej40DG58wnxmbHGM,1434
18
+ pabot/py3/coordinator.py,sha256=kBshCzA_1QX_f0WNk42QBJyDYSwSlNM-UEBxOReOj6E,2313
19
+ pabot/py3/messages.py,sha256=7mFr4_0x1JHm5sW8TvKq28Xs_JoeIGku2bX7AyO0kng,2557
20
+ pabot/py3/worker.py,sha256=5rfp4ZiW6gf8GRz6eC0-KUkfx847A91lVtRYpLAv2sg,1612
21
+ robotframework_pabot-5.2.0b1.dist-info/METADATA,sha256=_7b2wWKxeuFlEbRCz_sHwmrWQCwp85v-rl9HX-mScyo,23811
22
+ robotframework_pabot-5.2.0b1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
+ robotframework_pabot-5.2.0b1.dist-info/entry_points.txt,sha256=JpAIFADTeFOQWdwmn56KpAil8V3-41ZC5ICXCYm3Ng0,43
24
+ robotframework_pabot-5.2.0b1.dist-info/top_level.txt,sha256=t3OwfEAsSxyxrhjy_GCJYHKbV_X6AIsgeLhYeHvObG4,6
25
+ robotframework_pabot-5.2.0b1.dist-info/RECORD,,
@@ -1,22 +0,0 @@
1
- pabot/SharedLibrary.py,sha256=mIipGs3ZhKYEakKprcbrMI4P_Un6qI8gE7086xpHaLY,2552
2
- pabot/__init__.py,sha256=QKXV5e-W0g2tAcx-NzbFZscMZr1HtBUzDrpQDrURXBk,200
3
- pabot/arguments.py,sha256=m38y8mXKJ5BHlxSrsEI0gXlkzR5hv88G9i-FL_BouQ4,9168
4
- pabot/clientwrapper.py,sha256=yz7battGs0exysnDeLDWJuzpb2Q-qSjitwxZMO2TlJw,231
5
- pabot/coordinatorwrapper.py,sha256=nQQ7IowD6c246y8y9nsx0HZbt8vS2XODhPVDjm-lyi0,195
6
- pabot/execution_items.py,sha256=zDVGW0AAeVbM-scC3Yui2TxvIPx1wYyFKHTPU2BkJkY,13329
7
- pabot/pabot.py,sha256=j_CtB8S8gZ5qBSlXKuv_7Mhj7i5RVHm7X6tg1l_Fp6o,79549
8
- pabot/pabotlib.py,sha256=FRZKaKy1ybyRkE-0SpaCsUWzxZAzNNU5dAywSm1QoPk,22324
9
- pabot/result_merger.py,sha256=ST2szeXoaD3ipwr_vhIUH2SihlxhoXiOQu2Zj2VowyA,9674
10
- pabot/robotremoteserver.py,sha256=L3O2QRKSGSE4ux5M1ip5XJMaelqaxQWJxd9wLLdtpzM,22272
11
- pabot/workerwrapper.py,sha256=BdELUVDs5BmEkdNBcYTlnP22Cj0tUpZEunYQMAKyKWU,185
12
- pabot/py3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- pabot/py3/client.py,sha256=Od9L4vZ0sozMHq_W_ITQHBBt8kAej40DG58wnxmbHGM,1434
14
- pabot/py3/coordinator.py,sha256=kBshCzA_1QX_f0WNk42QBJyDYSwSlNM-UEBxOReOj6E,2313
15
- pabot/py3/messages.py,sha256=7mFr4_0x1JHm5sW8TvKq28Xs_JoeIGku2bX7AyO0kng,2557
16
- pabot/py3/worker.py,sha256=5rfp4ZiW6gf8GRz6eC0-KUkfx847A91lVtRYpLAv2sg,1612
17
- robotframework_pabot-5.0.0.dist-info/licenses/LICENSE.txt,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
18
- robotframework_pabot-5.0.0.dist-info/METADATA,sha256=-vtvV7PlcmXw8p1RmrDuLGw0LNcC_jwzMVVlQvyDuPE,20880
19
- robotframework_pabot-5.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
- robotframework_pabot-5.0.0.dist-info/entry_points.txt,sha256=JpAIFADTeFOQWdwmn56KpAil8V3-41ZC5ICXCYm3Ng0,43
21
- robotframework_pabot-5.0.0.dist-info/top_level.txt,sha256=t3OwfEAsSxyxrhjy_GCJYHKbV_X6AIsgeLhYeHvObG4,6
22
- robotframework_pabot-5.0.0.dist-info/RECORD,,