Skip to content

Commit 273a63e

Browse files
authored
Fix test statistics reporting issue in pool mode - consolidate results properly to prevent duplicate counting (#5089)
1 parent cd6fec7 commit 273a63e

File tree

9 files changed

+891
-26
lines changed

9 files changed

+891
-26
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ You don't need to worry about asynchronous nature of NodeJS or about various API
6464
- Also plays nice with TypeScript.
6565
- </> Smart locators: use names, labels, matching text, CSS or XPath to locate elements.
6666
- 🌐 Interactive debugging shell: pause test at any point and try different commands in a browser.
67+
-**Parallel testing** with dynamic test pooling for optimal load balancing and performance.
6768
- Easily create tests, pageobjects, stepobjects with CLI generators.
6869

6970
## Installation

bin/codecept.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ program
196196
.option('-i, --invert', 'inverts --grep matches')
197197
.option('-o, --override [value]', 'override current config options')
198198
.option('--suites', 'parallel execution of suites not single tests')
199+
.option('--by <strategy>', 'test distribution strategy: "test" (pre-assign individual tests), "suite" (pre-assign test suites), or "pool" (dynamic distribution for optimal load balancing, recommended)')
199200
.option(commandFlags.debug.flag, commandFlags.debug.description)
200201
.option(commandFlags.verbose.flag, commandFlags.verbose.description)
201202
.option('--features', 'run only *.feature files and skip tests')

docs/commands.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,32 @@ DEBUG=codeceptjs:* npx codeceptjs run
102102

103103
## Run Workers
104104

105-
Run tests in parallel threads.
105+
Run tests in parallel threads. CodeceptJS supports different distribution strategies for optimal performance.
106106

107-
```
107+
```bash
108+
# Run with 3 workers using default strategy (pre-assign tests)
108109
npx codeceptjs run-workers 3
110+
111+
# Run with pool mode for dynamic test distribution (recommended)
112+
npx codeceptjs run-workers 3 --by pool
113+
114+
# Run with suite distribution
115+
npx codeceptjs run-workers 3 --by suite
116+
117+
# Pool mode with filtering
118+
npx codeceptjs run-workers 4 --by pool --grep "@smoke"
109119
```
110120

121+
**Test Distribution Strategies:**
122+
123+
- `--by test` (default): Pre-assigns individual tests to workers
124+
- `--by suite`: Pre-assigns entire test suites to workers
125+
- `--by pool`: Dynamic distribution for optimal load balancing (recommended for best performance)
126+
127+
The pool mode provides the best load balancing by maintaining tests in a shared pool and distributing them dynamically as workers become available. This prevents workers from sitting idle and ensures optimal CPU utilization, especially when tests have varying execution times.
128+
129+
See [Parallel Execution](/parallel) documentation for more details.
130+
111131
## Run Rerun <Badge text="Since 3.3.6" type="warning"/>
112132

113133
Run tests multiple times to detect and fix flaky tests.

docs/parallel.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,88 @@ By default, the tests are assigned one by one to the available workers this may
3232
npx codeceptjs run-workers --suites 2
3333
```
3434

35+
### Test Distribution Strategies
36+
37+
CodeceptJS supports three different strategies for distributing tests across workers:
38+
39+
#### Default Strategy (`--by test`)
40+
Tests are pre-assigned to workers at startup, distributing them evenly across all workers. Each worker gets a predetermined set of tests to run.
41+
42+
```sh
43+
npx codeceptjs run-workers 3 --by test
44+
```
45+
46+
#### Suite Strategy (`--by suite`)
47+
Test suites are pre-assigned to workers, with all tests in a suite running on the same worker. This ensures better test isolation but may lead to uneven load distribution.
48+
49+
```sh
50+
npx codeceptjs run-workers 3 --by suite
51+
```
52+
53+
#### Pool Strategy (`--by pool`) - **Recommended for optimal performance**
54+
Tests are maintained in a shared pool and distributed dynamically to workers as they become available. This provides the best load balancing and resource utilization.
55+
56+
```sh
57+
npx codeceptjs run-workers 3 --by pool
58+
```
59+
60+
## Dynamic Test Pooling Mode
61+
62+
The pool mode enables dynamic test distribution for improved worker load balancing. Instead of pre-assigning tests to workers at startup, tests are stored in a shared pool and distributed on-demand as workers become available.
63+
64+
### Benefits of Pool Mode
65+
66+
* **Better load balancing**: Workers never sit idle while others are still running long tests
67+
* **Improved performance**: Especially beneficial when tests have varying execution times
68+
* **Optimal resource utilization**: All CPU cores stay busy until the entire test suite is complete
69+
* **Automatic scaling**: Workers continuously process tests until the pool is empty
70+
71+
### When to Use Pool Mode
72+
73+
Pool mode is particularly effective in these scenarios:
74+
75+
* **Uneven test execution times**: When some tests take significantly longer than others
76+
* **Large test suites**: With hundreds or thousands of tests where load balancing matters
77+
* **Mixed test types**: When combining unit tests, integration tests, and end-to-end tests
78+
* **CI/CD pipelines**: For consistent and predictable test execution times
79+
80+
### Usage Examples
81+
82+
```bash
83+
# Basic pool mode with 4 workers
84+
npx codeceptjs run-workers 4 --by pool
85+
86+
# Pool mode with grep filtering
87+
npx codeceptjs run-workers 3 --by pool --grep "@smoke"
88+
89+
# Pool mode in debug mode
90+
npx codeceptjs run-workers 2 --by pool --debug
91+
92+
# Pool mode with specific configuration
93+
npx codeceptjs run-workers 3 --by pool -c codecept.conf.js
94+
```
95+
96+
### How Pool Mode Works
97+
98+
1. **Pool Creation**: All tests are collected into a shared pool of test identifiers
99+
2. **Worker Initialization**: The specified number of workers are spawned
100+
3. **Dynamic Assignment**: Workers request tests from the pool when they're ready
101+
4. **Continuous Processing**: Each worker runs one test, then immediately requests the next
102+
5. **Automatic Completion**: Workers exit when the pool is empty and no more tests remain
103+
104+
### Performance Comparison
105+
106+
```bash
107+
# Traditional mode - tests pre-assigned, some workers may finish early
108+
npx codeceptjs run-workers 3 --by test # ✓ Good for uniform test times
109+
110+
# Suite mode - entire suites assigned to workers
111+
npx codeceptjs run-workers 3 --by suite # ✓ Good for test isolation
112+
113+
# Pool mode - tests distributed dynamically
114+
npx codeceptjs run-workers 3 --by pool # ✓ Best for mixed test execution times
115+
```
116+
35117
## Test stats with Parallel Execution by Workers
36118

37119
```js

lib/command/run-workers.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,22 @@ module.exports = async function (workerCount, selectedRuns, options) {
1010

1111
const { config: testConfig, override = '' } = options
1212
const overrideConfigs = tryOrDefault(() => JSON.parse(override), {})
13-
const by = options.suites ? 'suite' : 'test'
13+
14+
// Determine test split strategy
15+
let by = 'test' // default
16+
if (options.by) {
17+
// Explicit --by option takes precedence
18+
by = options.by
19+
} else if (options.suites) {
20+
// Legacy --suites option
21+
by = 'suite'
22+
}
23+
24+
// Validate the by option
25+
const validStrategies = ['test', 'suite', 'pool']
26+
if (!validStrategies.includes(by)) {
27+
throw new Error(`Invalid --by strategy: ${by}. Valid options are: ${validStrategies.join(', ')}`)
28+
}
1429
delete options.parent
1530
const config = {
1631
by,

0 commit comments

Comments
 (0)