0
# Runner Management
1
2
Core runner functionality for managing worker processes and coordinating test execution across multiple isolated environments.
3
4
## Capabilities
5
6
### LocalRunner Class
7
8
Main class that manages the worker pool, handles Xvfb initialization, and coordinates test execution.
9
10
```typescript { .api }
11
/**
12
* Main runner class for managing worker processes
13
*/
14
class LocalRunner {
15
workerPool: Record<string, WorkerInstance>;
16
stdout: WritableStreamBuffer;
17
stderr: WritableStreamBuffer;
18
19
constructor(options: never, config: WebdriverIO.Config);
20
initialize(): Promise<void>;
21
getWorkerCount(): number;
22
run(args: RunArgs): Promise<WorkerInstance>;
23
shutdown(): Promise<boolean>;
24
}
25
```
26
27
### Constructor
28
29
Creates a new LocalRunner instance with configuration.
30
31
```typescript { .api }
32
/**
33
* Create a LocalRunner instance
34
* @param options - First parameter (unused, pass {} as never)
35
* @param config - WebdriverIO configuration object
36
*/
37
constructor(options: never, config: WebdriverIO.Config);
38
```
39
40
**Usage Example:**
41
42
```typescript
43
import LocalRunner from "@wdio/local-runner";
44
45
const runner = new LocalRunner({} as never, {
46
autoXvfb: true,
47
outputDir: "./logs",
48
runnerEnv: { NODE_ENV: "test" },
49
xvfbAutoInstall: true,
50
groupLogsByTestSpec: false
51
} as WebdriverIO.Config);
52
```
53
54
### Initialize Runner
55
56
Initialize the local runner environment. This method performs minimal setup as Xvfb initialization is handled lazily during the first worker creation.
57
58
```typescript { .api }
59
/**
60
* Initialize local runner environment
61
* @returns Promise that resolves when initialization is complete
62
*/
63
initialize(): Promise<void>;
64
```
65
66
**Usage Example:**
67
68
```typescript
69
await runner.initialize();
70
console.log('Runner initialized');
71
```
72
73
### Get Worker Count
74
75
Get the number of currently active worker processes.
76
77
```typescript { .api }
78
/**
79
* Get count of active workers in the pool
80
* @returns Number of active worker instances
81
*/
82
getWorkerCount(): number;
83
```
84
85
**Usage Example:**
86
87
```typescript
88
const activeWorkers = runner.getWorkerCount();
89
console.log(`Currently running ${activeWorkers} workers`);
90
```
91
92
### Run Worker
93
94
Create and start a new worker process to execute tests.
95
96
```typescript { .api }
97
/**
98
* Create and run a worker process
99
* @param args - Run arguments including command, capabilities, and specs
100
* @returns Promise resolving to WorkerInstance
101
*/
102
run(args: RunArgs): Promise<WorkerInstance>;
103
```
104
105
**Usage Example:**
106
107
```typescript
108
const worker = await runner.run({
109
cid: "0-0",
110
command: "run",
111
configFile: "/path/to/wdio.conf.js",
112
args: {},
113
caps: {
114
browserName: "chrome",
115
"goog:chromeOptions": { args: ["--headless"] }
116
},
117
specs: ["./test/login.spec.js", "./test/dashboard.spec.js"],
118
execArgv: [],
119
retries: 2
120
});
121
122
// Worker will be added to workerPool automatically
123
console.log(`Started worker ${worker.cid}`);
124
```
125
126
### Shutdown Workers
127
128
Shutdown all worker processes with graceful timeout handling.
129
130
```typescript { .api }
131
/**
132
* Shutdown all worker processes
133
* @returns Promise resolving to boolean indicating successful shutdown
134
*/
135
shutdown(): Promise<boolean>;
136
```
137
138
**Usage Example:**
139
140
```typescript
141
// Shutdown all workers (waits up to 5 seconds for graceful shutdown)
142
const shutdownSuccess = await runner.shutdown();
143
144
if (shutdownSuccess) {
145
console.log('All workers shut down successfully');
146
} else {
147
console.log('Some workers did not shut down gracefully');
148
}
149
```
150
151
## Configuration Options
152
153
### Xvfb Configuration
154
155
Virtual display configuration for headless browser testing.
156
157
```typescript { .api }
158
interface XvfbConfig {
159
autoXvfb?: boolean; // Enable/disable Xvfb (default: enabled)
160
xvfbAutoInstall?: string | boolean | {
161
mode: string;
162
command: string;
163
}; // Auto-install Xvfb if missing
164
xvfbAutoInstallMode?: string; // Installation mode (e.g., 'sudo')
165
xvfbAutoInstallCommand?: string; // Custom installation command
166
xvfbMaxRetries?: number; // Maximum retry attempts
167
xvfbRetryDelay?: number; // Delay between retry attempts
168
}
169
```
170
171
### Output Configuration
172
173
Configuration for worker output and logging.
174
175
```typescript { .api }
176
interface OutputConfig {
177
outputDir?: string; // Directory for log files
178
runnerEnv?: Record<string, any>; // Environment variables for workers
179
groupLogsByTestSpec?: boolean; // Group logs by test specification
180
}
181
```
182
183
### Watch Mode Configuration
184
185
Configuration for file watching and session reuse.
186
187
```typescript { .api }
188
interface WatchConfig {
189
watch?: boolean; // Enable watch mode
190
}
191
```
192
193
## Error Handling
194
195
### Xvfb Initialization Errors
196
197
Xvfb initialization failures are handled gracefully and logged as warnings.
198
199
```typescript
200
// Xvfb errors don't cause runner failure
201
const runner = new LocalRunner({} as never, { autoXvfb: true });
202
203
try {
204
await runner.run({
205
cid: "0-0",
206
command: "run",
207
// ... other options
208
});
209
} catch (error) {
210
// Xvfb errors won't cause this to throw
211
console.log('Worker started despite Xvfb issues');
212
}
213
```
214
215
### Worker Shutdown Timeout
216
217
Worker shutdown includes timeout handling to prevent hanging processes.
218
219
```typescript
220
// Shutdown will resolve after 5 seconds maximum
221
const shutdownPromise = runner.shutdown();
222
223
// You can also handle partial shutdown scenarios
224
const success = await shutdownPromise;
225
if (!success) {
226
console.log('Some workers required forceful termination');
227
}
228
```
229
230
## Advanced Usage
231
232
### Multiple Capability Testing
233
234
```typescript
235
const runner = new LocalRunner({} as never, config);
236
237
// Start multiple workers for different browser capabilities
238
const chromeWorker = await runner.run({
239
cid: "chrome-0",
240
command: "run",
241
caps: { browserName: "chrome" },
242
specs: ["./test/chrome-specific.spec.js"],
243
// ... other options
244
});
245
246
const firefoxWorker = await runner.run({
247
cid: "firefox-0",
248
command: "run",
249
caps: { browserName: "firefox" },
250
specs: ["./test/firefox-specific.spec.js"],
251
// ... other options
252
});
253
254
console.log(`Running ${runner.getWorkerCount()} workers`); // 2
255
```
256
257
### Environment Customization
258
259
```typescript
260
const runner = new LocalRunner({} as never, {
261
runnerEnv: {
262
NODE_ENV: "test",
263
API_BASE_URL: "https://staging.example.com",
264
FORCE_COLOR: "1"
265
},
266
outputDir: "./test-logs"
267
});
268
```