Custom Services
You can write your own custom service for the WDIO test runner to custom-fit your needs.
Services are add-ons that are created for reusable logic to simplify tests, manage your test suite and integrate results. Services have access to all the same hooks available in the wdio.conf.js
.
There are two types of services that can be defined: a launcher service that only has access to the onPrepare
, onWorkerStart
, onWorkerEnd
and onComplete
hook which are only executed once per test run, and a worker service that has access to all other hooks and is being executed for each worker. Note that you can not share (global) variables between both types of services as worker services run in a different (worker) process.
A launcher service can be defined as follows:
export default class CustomLauncherService {
// If a hook returns a promise, WebdriverIO will wait until that promise is resolved to continue.
async onPrepare(config, capabilities) {
// TODO: something before all workers launch
}
onComplete(exitCode, config, capabilities) {
// TODO: something after the workers shutdown
}
// custom service methods ...
}
Whereas a worker service should look like this:
export default class CustomWorkerService {
/**
* `serviceOptions` contains all options specific to the service
* e.g. if defined as follows:
*
* ```
* services: [['custom', { foo: 'bar' }]]
* ```
*
* the `serviceOptions` parameter will be: `{ foo: 'bar' }`
*/
constructor (serviceOptions, capabilities, config) {
this.options = serviceOptions
}
/**
* this browser object is passed in here for the first time
*/
async before(config, capabilities, browser) {
this.browser = browser
// TODO: something before all tests are run, e.g.:
await this.browser.setWindowSize(1024, 768)
}
after(exitCode, config, capabilities) {
// TODO: something after all tests are run
}
beforeTest(test, context) {
// TODO: something before each Mocha/Jasmine test run
}
beforeScenario(test, context) {
// TODO: something before each Cucumber scenario run
}
// other hooks or custom service methods ...
}
It is recommended to store the browser object through the passed in parameter in the constructor. Lastly expose both types of workers as following:
import CustomLauncherService from './launcher'
import CustomWorkerService from './service'
export default CustomWorkerService
export const launcher = CustomLauncherService
If you are using TypeScript and want to make sure that hook methods parameter are type safe, you can define your service class as follows:
import type { Capabilities, Options, Services } from '@wdio/types'
export default class CustomWorkerService implements Services.ServiceInstance {
constructor (
private _options: MyServiceOptions,
private _capabilities: Capabilities.RemoteCapability,
private _config: Options.Testrunner
) {
// ...
}
// ...
}