robotframework-parallelrunner 0.3.1__tar.gz → 0.5.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.
@@ -1,20 +1,19 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotframework-parallelrunner
3
- Version: 0.3.1
3
+ Version: 0.5.0
4
4
  Summary: Run a keyword in parallel inside a single Robot Framework test case, with one clean, ordered log.html.
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
7
7
  Keywords: robotframework,robot-framework,parallel,threading,testing,automation
8
8
  Author: Cristian Garcia
9
9
  Author-email: cristian.garcia.vd@gmail.com
10
- Requires-Python: >=3.9
10
+ Requires-Python: >=3.10
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Framework :: Robot Framework
13
13
  Classifier: Framework :: Robot Framework :: Library
14
14
  Classifier: Intended Audience :: Developers
15
15
  Classifier: Operating System :: OS Independent
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.9
18
17
  Classifier: Programming Language :: Python :: 3.10
19
18
  Classifier: Programming Language :: Python :: 3.11
20
19
  Classifier: Programming Language :: Python :: 3.12
@@ -53,9 +52,10 @@ correctly ordered `log.html` plus a structured list of per-item results.
53
52
  pip install robotframework-parallelrunner
54
53
  ```
55
54
 
56
- Requires Python 3.9+ and Robot Framework 5.0+ (installed automatically).
57
- See [docs/INSTALLATION.md](https://github.com/cristiangarciavd/robotframework-parallelrunner/blob/main/docs/INSTALLATION.md) for development installs
58
- and upgrading from the pre-release import path.
55
+ Requires Python 3.10+ and Robot Framework 5.0+ (installed automatically).
56
+ See [docs/INSTALLATION.md](https://github.com/cristiangarciavd/robotframework-parallelrunner/blob/main/docs/INSTALLATION.md) for development installs,
57
+ upgrading from the pre-release import path, and Python 3.8/3.9 (no longer
58
+ supported, but 0.5.0 was tested and works on them).
59
59
 
60
60
  ## Quickstart
61
61
 
@@ -113,8 +113,8 @@ threading, buffering, and replay logic stay out of your `.robot` files.
113
113
  ## Summary of Benefits
114
114
 
115
115
  - **Speed.** Waiting time is overlapped instead of added up. In this repo's
116
- examples, 9 HTTP checks with a 1 s delay each drop from 13 s to 2 s with
117
- 9 workers, and 4 suites × 8 items × 1 s drop from 32.7 s to 4.6 s with
116
+ examples, 9 HTTP checks with a 1 s delay each drop from 13.9 s to 2.2 s with
117
+ 9 workers, and 4 suites × 8 items × 1 s drop from 32.9 s to 5.1 s with
118
118
  8 workers (see [Using It Together With pabot](#using-it-together-with-pabot)).
119
119
  - **Integrity.** Your `log.html` remains the single source of truth — no
120
120
  broken XML tags from concurrent writes.
@@ -183,7 +183,7 @@ pabot --processes 4 --pythonpath . atest/
183
183
  pabot --processes 4 --testlevelsplit --pythonpath . atest/
184
184
  ```
185
185
 
186
- Both commands pass the full acceptance suite of this repository (52 tests;
186
+ Both commands pass the full acceptance suite of this repository (82 tests;
187
187
  checked with pabot 5.2.2).
188
188
 
189
189
  How much time each one saves, from the offline
@@ -192,14 +192,14 @@ How much time each one saves, from the offline
192
192
 
193
193
  | Run | Wall-clock time | Speedup |
194
194
  |---|---|---|
195
- | robot, sequential loop | 32.7 s | ×1.0 |
196
- | robot + ParallelRunner (8 workers) | 4.6 s | ×7.1 |
197
- | pabot (4 processes), sequential loop | 10.6 s | ×3.1 |
198
- | pabot (4 processes) + ParallelRunner (8 workers) | 3.5 s | ×9.2 |
195
+ | robot, sequential loop | 32.9 s | ×1.0 |
196
+ | robot + ParallelRunner (8 workers) | 5.1 s | ×6.5 |
197
+ | pabot (4 processes), sequential loop | 12.4 s | ×2.7 |
198
+ | pabot (4 processes) + ParallelRunner (8 workers) | 4.6 s | ×7.2 |
199
199
 
200
200
  ParallelRunner removes the waiting *inside* each test, and pabot removes it
201
201
  *between* suites. With suites this short, pabot's process start-up (about
202
- 2.5 s here) is most of what's left, so the combination pays off more as
202
+ 3.5 s here) is most of what's left, so the combination pays off more as
203
203
  suites get longer.
204
204
 
205
205
  Things to keep in mind:
@@ -221,6 +221,31 @@ Things to keep in mind:
221
221
  could interfere with each other. Keep shared state per process, or split
222
222
  by suite.
223
223
 
224
+ ## How Is This Different From AsyncLibrary?
225
+
226
+ [AsyncLibrary](https://github.com/rlehfeld/robotframework-async-keyword)
227
+ (`pip install robotframework-async-keyword`) also runs keywords in threads
228
+ inside one test case. It runs *any* keyword, user keywords included: you
229
+ start each call with `Async Run` and collect it later with `Async Get`. It
230
+ buffers each call's output and replays it, so `log.html` keeps the full
231
+ nested keyword structure. To do that, it works with Robot Framework's
232
+ internal execution context and output.
233
+
234
+ | | **AsyncLibrary** | **ParallelRunner** |
235
+ |---|---|---|
236
+ | Runs | Any keyword, including user keywords | A method of a Python library that accepts `_logger` |
237
+ | Usage | `Async Run` per call, `Async Get` later | One `Run Parallel Scenarios` call over a list, or `repeat=N` |
238
+ | Concurrency | Python's default thread pool size | `ROBOT_THREAD_WORKERS` |
239
+ | Hung calls | `Async Get timeout=...` stops waiting for them | `call_timeout` fails only that call and frees its slot for the next item |
240
+ | Failures | `Async Get` raises the call's error | One failure listing every failed item, or a `PASS`/`FAIL` per item with `fail_on_error=False` |
241
+ | Robot internals | Works with the internal execution context and output | Not patched; logs only from the main thread, through the public logger API; tested on Robot Framework 5, 6 and 7 |
242
+
243
+ Use AsyncLibrary when the work lives in user keywords (or in library
244
+ keywords you can't change), or when you want to start something in the
245
+ background, run other steps, and collect it later. Use ParallelRunner to fan
246
+ one Python keyword out over many items as a single batch, with a bounded
247
+ worker pool, per-call timeouts and one failure report for the whole batch.
248
+
224
249
  ## When Not To Use This
225
250
 
226
251
  - **CPU-bound work.** Threads share Python's GIL — number crunching won't
@@ -230,11 +255,6 @@ Things to keep in mind:
230
255
  made thread-safe for you; your own keyword's side effects are not. If it
231
256
  writes to a shared variable, file, or object without a lock, running it
232
257
  concurrently can race the same way any multi-threaded code can.
233
- - **You need per-item retries or a per-item timeout.** Not implemented yet
234
- (see [ROADMAP.md](https://github.com/cristiangarciavd/robotframework-parallelrunner/blob/main/ROADMAP.md)). A Robot `[Timeout]` on the test or keyword does
235
- interrupt the whole batch when it expires and replays the logs collected so
236
- far, but calls that are already running can't be stopped: they keep running
237
- in the background until they return.
238
258
  - **You need process-level isolation** (a crash in one call shouldn't be
239
259
  able to affect another) or cross-machine parallelism — that's pabot's
240
260
  domain, not this library's.
@@ -19,9 +19,10 @@ correctly ordered `log.html` plus a structured list of per-item results.
19
19
  pip install robotframework-parallelrunner
20
20
  ```
21
21
 
22
- Requires Python 3.9+ and Robot Framework 5.0+ (installed automatically).
23
- See [docs/INSTALLATION.md](https://github.com/cristiangarciavd/robotframework-parallelrunner/blob/main/docs/INSTALLATION.md) for development installs
24
- and upgrading from the pre-release import path.
22
+ Requires Python 3.10+ and Robot Framework 5.0+ (installed automatically).
23
+ See [docs/INSTALLATION.md](https://github.com/cristiangarciavd/robotframework-parallelrunner/blob/main/docs/INSTALLATION.md) for development installs,
24
+ upgrading from the pre-release import path, and Python 3.8/3.9 (no longer
25
+ supported, but 0.5.0 was tested and works on them).
25
26
 
26
27
  ## Quickstart
27
28
 
@@ -79,8 +80,8 @@ threading, buffering, and replay logic stay out of your `.robot` files.
79
80
  ## Summary of Benefits
80
81
 
81
82
  - **Speed.** Waiting time is overlapped instead of added up. In this repo's
82
- examples, 9 HTTP checks with a 1 s delay each drop from 13 s to 2 s with
83
- 9 workers, and 4 suites × 8 items × 1 s drop from 32.7 s to 4.6 s with
83
+ examples, 9 HTTP checks with a 1 s delay each drop from 13.9 s to 2.2 s with
84
+ 9 workers, and 4 suites × 8 items × 1 s drop from 32.9 s to 5.1 s with
84
85
  8 workers (see [Using It Together With pabot](#using-it-together-with-pabot)).
85
86
  - **Integrity.** Your `log.html` remains the single source of truth — no
86
87
  broken XML tags from concurrent writes.
@@ -149,7 +150,7 @@ pabot --processes 4 --pythonpath . atest/
149
150
  pabot --processes 4 --testlevelsplit --pythonpath . atest/
150
151
  ```
151
152
 
152
- Both commands pass the full acceptance suite of this repository (52 tests;
153
+ Both commands pass the full acceptance suite of this repository (82 tests;
153
154
  checked with pabot 5.2.2).
154
155
 
155
156
  How much time each one saves, from the offline
@@ -158,14 +159,14 @@ How much time each one saves, from the offline
158
159
 
159
160
  | Run | Wall-clock time | Speedup |
160
161
  |---|---|---|
161
- | robot, sequential loop | 32.7 s | ×1.0 |
162
- | robot + ParallelRunner (8 workers) | 4.6 s | ×7.1 |
163
- | pabot (4 processes), sequential loop | 10.6 s | ×3.1 |
164
- | pabot (4 processes) + ParallelRunner (8 workers) | 3.5 s | ×9.2 |
162
+ | robot, sequential loop | 32.9 s | ×1.0 |
163
+ | robot + ParallelRunner (8 workers) | 5.1 s | ×6.5 |
164
+ | pabot (4 processes), sequential loop | 12.4 s | ×2.7 |
165
+ | pabot (4 processes) + ParallelRunner (8 workers) | 4.6 s | ×7.2 |
165
166
 
166
167
  ParallelRunner removes the waiting *inside* each test, and pabot removes it
167
168
  *between* suites. With suites this short, pabot's process start-up (about
168
- 2.5 s here) is most of what's left, so the combination pays off more as
169
+ 3.5 s here) is most of what's left, so the combination pays off more as
169
170
  suites get longer.
170
171
 
171
172
  Things to keep in mind:
@@ -187,6 +188,31 @@ Things to keep in mind:
187
188
  could interfere with each other. Keep shared state per process, or split
188
189
  by suite.
189
190
 
191
+ ## How Is This Different From AsyncLibrary?
192
+
193
+ [AsyncLibrary](https://github.com/rlehfeld/robotframework-async-keyword)
194
+ (`pip install robotframework-async-keyword`) also runs keywords in threads
195
+ inside one test case. It runs *any* keyword, user keywords included: you
196
+ start each call with `Async Run` and collect it later with `Async Get`. It
197
+ buffers each call's output and replays it, so `log.html` keeps the full
198
+ nested keyword structure. To do that, it works with Robot Framework's
199
+ internal execution context and output.
200
+
201
+ | | **AsyncLibrary** | **ParallelRunner** |
202
+ |---|---|---|
203
+ | Runs | Any keyword, including user keywords | A method of a Python library that accepts `_logger` |
204
+ | Usage | `Async Run` per call, `Async Get` later | One `Run Parallel Scenarios` call over a list, or `repeat=N` |
205
+ | Concurrency | Python's default thread pool size | `ROBOT_THREAD_WORKERS` |
206
+ | Hung calls | `Async Get timeout=...` stops waiting for them | `call_timeout` fails only that call and frees its slot for the next item |
207
+ | Failures | `Async Get` raises the call's error | One failure listing every failed item, or a `PASS`/`FAIL` per item with `fail_on_error=False` |
208
+ | Robot internals | Works with the internal execution context and output | Not patched; logs only from the main thread, through the public logger API; tested on Robot Framework 5, 6 and 7 |
209
+
210
+ Use AsyncLibrary when the work lives in user keywords (or in library
211
+ keywords you can't change), or when you want to start something in the
212
+ background, run other steps, and collect it later. Use ParallelRunner to fan
213
+ one Python keyword out over many items as a single batch, with a bounded
214
+ worker pool, per-call timeouts and one failure report for the whole batch.
215
+
190
216
  ## When Not To Use This
191
217
 
192
218
  - **CPU-bound work.** Threads share Python's GIL — number crunching won't
@@ -196,11 +222,6 @@ Things to keep in mind:
196
222
  made thread-safe for you; your own keyword's side effects are not. If it
197
223
  writes to a shared variable, file, or object without a lock, running it
198
224
  concurrently can race the same way any multi-threaded code can.
199
- - **You need per-item retries or a per-item timeout.** Not implemented yet
200
- (see [ROADMAP.md](https://github.com/cristiangarciavd/robotframework-parallelrunner/blob/main/ROADMAP.md)). A Robot `[Timeout]` on the test or keyword does
201
- interrupt the whole batch when it expires and replays the logs collected so
202
- far, but calls that are already running can't be stopped: they keep running
203
- in the background until they return.
204
225
  - **You need process-level isolation** (a crash in one call shouldn't be
205
226
  able to affect another) or cross-machine parallelism — that's pabot's
206
227
  domain, not this library's.
@@ -6,12 +6,12 @@ build-backend = "poetry.core.masonry.api"
6
6
  name = "robotframework-parallelrunner"
7
7
  # Single source of truth for the version: bump with `poetry version patch|minor|major`.
8
8
  # ParallelRunner.__version__ / ROBOT_LIBRARY_VERSION read it back from the installed metadata.
9
- version = "0.3.1"
9
+ version = "0.5.0"
10
10
  description = "Run a keyword in parallel inside a single Robot Framework test case, with one clean, ordered log.html."
11
11
  readme = "README.md"
12
12
  license = "MIT"
13
13
  license-files = ["LICENSE"]
14
- requires-python = ">=3.9"
14
+ requires-python = ">=3.10"
15
15
  authors = [
16
16
  { name = "Cristian Garcia", email = "cristian.garcia.vd@gmail.com" },
17
17
  ]
@@ -30,7 +30,6 @@ classifiers = [
30
30
  "Intended Audience :: Developers",
31
31
  "Operating System :: OS Independent",
32
32
  "Programming Language :: Python :: 3",
33
- "Programming Language :: Python :: 3.9",
34
33
  "Programming Language :: Python :: 3.10",
35
34
  "Programming Language :: Python :: 3.11",
36
35
  "Programming Language :: Python :: 3.12",
@@ -13,7 +13,7 @@ Keyword documentation:
13
13
  https://cristiangarciavd.github.io/robotframework-parallelrunner/ParallelRunner.html
14
14
  """
15
15
 
16
- from .parallel_library import ParallelLibrary, ParallelRunner, ParallelTaskError
16
+ from .parallel_library import ParallelLibrary, ParallelRunner, ParallelTaskError, log_to_robot
17
17
  from .version import __version__
18
18
 
19
- __all__ = ["ParallelRunner", "ParallelLibrary", "ParallelTaskError", "__version__"]
19
+ __all__ = ["ParallelRunner", "ParallelLibrary", "ParallelTaskError", "log_to_robot", "__version__"]