Run JS tests when device Slots are limited

Below you can find information on how to organize JS test execution in case of limited device Slots.

Prerequisites

  • Existing test, which is written using the WebdriverIO framework.
  • List of devices, where these tests should be executed.
  • Plan with limited device Slots for the Test Automation.

Prepare capabilities with the device UDIDs for planned usage

To ensure that tests will be executed on a particular devices, it’s necessary to prepare capabilities for the device UDIDs.
Below you can find an example for a WebdriverIO test configuration.

const KEY = 'mobitru_ak_...';
const BILLING_UNIT = '<TEAM_CODE>';

const credentials = `${BILLING_UNIT}:${KEY}`;
const encodedCredentials = Buffer.from(credentials).toString('base64');

exports.config = {
    runner: 'local',
    protocol: 'https',
    hostname: `@app.mobitru.com`,
    headers: {
        Authorization: `Basic ${encodedCredentials}`
    },
    path: '/wd/hub',
    port: 443,
...
    capabilities: [
        {
            platformName: 'Android',
            'appium:automationName': 'UIAutomator2',
            'appium:browserName': 'chrome',
            'appium:udid': '4C071FDAP002SW',
        },
        {
            platformName: 'Android',
            'appium:automationName': 'UIAutomator2',
            'appium:browserName': 'chrome',
            'appium:udid': '26281JEGR04493',
        },
        {
            platformName: 'Android',
            'appium:automationName': 'UIAutomator2',
            'appium:browserName': 'chrome',
            'appium:udid': 'R5CY23ZSTNF',

        },
        {
            platformName: 'Android',
            'appium:automationName': 'UIAutomator2',
            'appium:browserName': 'chrome',
            'appium:udid': '28101FDH3009BP',

        }
    ],
    waitForTimeout: 10000, // Default timeout for wait commands
  ...
};

Set the ‘maxInstances’ property to the number of threads

The number of threads should be related to the number of available Slots. In this case, avoiding issues with concurrent device usage is possible.
Below you can find an example of setting the ‘maxInstances‘ property.

const KEY = 'mobitru_ak_...';
const BILLING_UNIT = '<TEAM_CODE>';

const credentials = `${BILLING_UNIT}:${KEY}`;
const encodedCredentials = Buffer.from(credentials).toString('base64');

exports.config = {
    runner: 'local',
    protocol: 'https',
    hostname: `@app.mobitru.com`,
    headers: {
        Authorization: `Basic ${encodedCredentials}`
    },
  ....
    maxInstances: 2,
    capabilities: [
        {
            platformName: 'Android',
            'appium:automationName': 'UIAutomator2',
            'appium:browserName': 'chrome',
            'appium:udid': '4C071FDAP002SW',
        },
   ....
};

Run tests using the configuration with the capabilities and the specified ‘maxInstances’ property

To run tests for limited device Slots, it’s necessary to execute them using the prepared WebDriverIO configuration.
Below, you can find an example of a test execution command for 2 available Slots and the corresponding console output.

Command:

node_modules/@wdio/cli/bin/wdio.js run wdio.android.web.conf.parallel.js

Output:

Execution of 4 workers started at 2025-09-12T15:37:55.769Z

2025-09-12T15:37:55.773Z INFO @wdio/cli:launcher: Run onPrepare hook
2025-09-12T15:37:55.775Z INFO @wdio/cli:launcher: Run onWorkerStart hook
2025-09-12T15:37:55.775Z INFO @wdio/cli:launcher: Run onWorkerStart hook
2025-09-12T15:37:55.775Z INFO @wdio/xvfb: XvfbManager.init() called
2025-09-12T15:37:55.775Z INFO @wdio/xvfb: Xvfb not needed on current platform
2025-09-12T15:37:55.775Z INFO @wdio/xvfb: XvfbManager.init() called
2025-09-12T15:37:55.775Z INFO @wdio/xvfb: Xvfb not needed on current platform
2025-09-12T15:37:55.776Z INFO @wdio/local-runner: Start worker 0-0 with arg: run wdio.android.web.conf.parallel.js
2025-09-12T15:37:55.787Z INFO @wdio/xvfb:ProcessFactory: xvfb-run not found, falling back to regular fork
2025-09-12T15:37:55.787Z INFO @wdio/xvfb:ProcessFactory: ProcessFactory: shouldRun=false, isAvailable=false
2025-09-12T15:37:55.787Z INFO @wdio/xvfb:ProcessFactory: Creating worker process with regular fork
2025-09-12T15:37:55.788Z INFO @wdio/local-runner: Start worker 1-0 with arg: run wdio.android.web.conf.parallel.js
2025-09-12T15:37:55.797Z INFO @wdio/xvfb:ProcessFactory: xvfb-run not found, falling back to regular fork
2025-09-12T15:37:55.797Z INFO @wdio/xvfb:ProcessFactory: ProcessFactory: shouldRun=false, isAvailable=false
2025-09-12T15:37:55.797Z INFO @wdio/xvfb:ProcessFactory: Creating worker process with regular fork
2025-09-12T15:37:55.798Z DEBUG @wdio/local-runner: Send command run to worker with cid "0-0"
2025-09-12T15:37:55.798Z DEBUG @wdio/local-runner: Send command run to worker with cid "1-0"
[0-0] 2025-09-12T15:37:56.140Z INFO @wdio/local-runner: Run worker command: run
[1-0] 2025-09-12T15:37:56.140Z INFO @wdio/local-runner: Run worker command: run
[1-0] 2025-09-12T15:37:56.144Z DEBUG @wdio/runner: init remote session
[0-0] 2025-09-12T15:37:56.144Z DEBUG @wdio/runner: init remote session
[0-0] RUNNING in Android on Android - file:///test/specs/web-appium-demo.js
[0-0] 2025-09-12T15:37:56.222Z DEBUG @wdio/runner: init remote session
[1-0] RUNNING in Android on Android - file:///test/specs/web-appium-demo.js
[1-0] 2025-09-12T15:37:56.223Z DEBUG @wdio/runner: init remote session
[0-0] 2025-09-12T15:37:56.223Z INFO webdriver: Initiate new session using the WebDriver protocol
[0-0] 2025-09-12T15:37:56.223Z INFO @wdio/utils: Connecting to existing driver at https://@app.mobitru.com:443/wd/hub
[1-0] 2025-09-12T15:37:56.223Z INFO webdriver: Initiate new session using the WebDriver protocol
[1-0] 2025-09-12T15:37:56.223Z INFO @wdio/utils: Connecting to existing driver at https://@app.mobitru.com:443/wd/hub
[0-0] 2025-09-12T15:37:56.227Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session
[1-0] 2025-09-12T15:37:56.227Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session
[1-0] 2025-09-12T15:38:11.957Z INFO webdriver: COMMAND setTimeouts(3000, 30000, undefined)
[1-0] 2025-09-12T15:38:11.957Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session/7f72bd06-9b4a-4b04-8f4d-0558ac56c934/timeouts
[1-0] 2025-09-12T15:38:11.958Z INFO webdriver: DATA { implicit: 3000, pageLoad: 30000 }
[0-0] 2025-09-12T15:38:12.063Z INFO webdriver: COMMAND setTimeouts(3000, 30000, undefined)
[0-0] 2025-09-12T15:38:12.063Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session/ee096322-1e2b-4a89-9847-6ba50e3eefb1/timeouts
[0-0] 2025-09-12T15:38:12.064Z INFO webdriver: DATA { implicit: 3000, pageLoad: 30000 }
[1-0] 2025-09-12T15:38:12.177Z INFO webdriver: RESULT null
[1-0] 2025-09-12T15:38:12.185Z DEBUG @wdio/utils:shim: Finished to run "beforeTest" hook in 0ms
[1-0] 2025-09-12T15:38:12.187Z INFO webdriver: COMMAND navigateTo("https://mobitru.com/")
[1-0] 2025-09-12T15:38:12.187Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session/7f72bd06-9b4a-4b04-8f4d-0558ac56c934/url
[1-0] 2025-09-12T15:38:12.187Z INFO webdriver: DATA { url: 'https://mobitru.com/' }
[0-0] 2025-09-12T15:38:12.285Z INFO webdriver: RESULT null
[0-0] 2025-09-12T15:38:12.287Z DEBUG @wdio/utils:shim: Finished to run "beforeTest" hook in 0ms
[0-0] 2025-09-12T15:38:12.289Z INFO webdriver: COMMAND navigateTo("https://mobitru.com/")
[0-0] 2025-09-12T15:38:12.289Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session/ee096322-1e2b-4a89-9847-6ba50e3eefb1/url
[0-0] 2025-09-12T15:38:12.289Z INFO webdriver: DATA { url: 'https://mobitru.com/' }
[0-0] 2025-09-12T15:38:15.143Z INFO webdriver: RESULT null

.....

[1-0] 2025-09-12T15:38:16.684Z DEBUG @wdio/utils:shim: Finished to run "afterTest" hook in 0ms
[1-0] 2025-09-12T15:38:16.698Z DEBUG @wdio/utils:shim: Finished to run "after" hook in 0ms
[1-0] 2025-09-12T15:38:16.698Z INFO webdriver: COMMAND deleteSession()
[1-0] 2025-09-12T15:38:16.699Z INFO webdriver: [DELETE] https://app.mobitru.com/wd/hub/session/7f72bd06-9b4a-4b04-8f4d-0558ac56c934
....
2025-09-12T15:38:17.067Z DEBUG @wdio/local-runner: Runner 0-0 finished with exit code 0
[0-0] PASSED in Android on Android - file:///test/specs/web-appium-demo.js
....

[1-0] 2025-09-12T15:38:17.069Z INFO webdriver: RESULT null
2025-09-12T15:38:17.176Z DEBUG @wdio/local-runner: Runner 1-0 finished with exit code 0
[1-0] PASSED in Android on Android - file:///test/specs/web-appium-demo.js
....

[2-0] 2025-09-12T15:38:17.511Z INFO @wdio/local-runner: Run worker command: run
[3-0] 2025-09-12T15:38:17.511Z INFO @wdio/local-runner: Run worker command: run
[2-0] 2025-09-12T15:38:17.515Z DEBUG @wdio/runner: init remote session
[3-0] 2025-09-12T15:38:17.515Z DEBUG @wdio/runner: init remote session
[2-0] RUNNING in Android on Android - file:///test/specs/web-appium-demo.js
[2-0] 2025-09-12T15:38:17.580Z DEBUG @wdio/runner: init remote session
[3-0] RUNNING in Android on Android - file:///test/specs/web-appium-demo.js
[3-0] 2025-09-12T15:38:17.581Z DEBUG @wdio/runner: init remote session
[2-0] 2025-09-12T15:38:17.581Z INFO webdriver: Initiate new session using the WebDriver protocol
[2-0] 2025-09-12T15:38:17.581Z INFO @wdio/utils: Connecting to existing driver at https://@app.mobitru.com:443/wd/hub
[3-0] 2025-09-12T15:38:17.581Z INFO webdriver: Initiate new session using the WebDriver protocol
[3-0] 2025-09-12T15:38:17.581Z INFO @wdio/utils: Connecting to existing driver at https://@app.mobitru.com:443/wd/hub
[3-0] 2025-09-12T15:38:17.585Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session
[2-0] 2025-09-12T15:38:17.585Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session
[2-0] 2025-09-12T15:38:32.065Z INFO webdriver: COMMAND setTimeouts(3000, 30000, undefined)
[2-0] 2025-09-12T15:38:32.065Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session/4fa532eb-83a8-4178-a9fa-c30166e21465/timeouts
[2-0] 2025-09-12T15:38:32.065Z INFO webdriver: DATA { implicit: 3000, pageLoad: 30000 }
[2-0] 2025-09-12T15:38:32.428Z INFO webdriver: RESULT null
[2-0] 2025-09-12T15:38:32.431Z DEBUG @wdio/utils:shim: Finished to run "beforeTest" hook in 1ms
[2-0] 2025-09-12T15:38:32.432Z INFO webdriver: COMMAND navigateTo("https://mobitru.com/")
[2-0] 2025-09-12T15:38:32.432Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session/4fa532eb-83a8-4178-a9fa-c30166e21465/url
[2-0] 2025-09-12T15:38:32.432Z INFO webdriver: DATA { url: 'https://mobitru.com/' }
[3-0] 2025-09-12T15:38:34.619Z INFO webdriver: COMMAND setTimeouts(3000, 30000, undefined)
[3-0] 2025-09-12T15:38:34.620Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session/beb23c9d-08b3-40c1-9305-3c6c8a71c9ab/timeouts
[3-0] 2025-09-12T15:38:34.620Z INFO webdriver: DATA { implicit: 3000, pageLoad: 30000 }
[3-0] 2025-09-12T15:38:35.033Z INFO webdriver: RESULT null
[3-0] 2025-09-12T15:38:35.035Z DEBUG @wdio/utils:shim: Finished to run "beforeTest" hook in 0ms
[3-0] 2025-09-12T15:38:35.035Z INFO webdriver: COMMAND navigateTo("https://mobitru.com/")
[3-0] 2025-09-12T15:38:35.036Z INFO webdriver: [POST] https://app.mobitru.com/wd/hub/session/beb23c9d-08b3-40c1-9305-3c6c8a71c9ab/url
[3-0] 2025-09-12T15:38:35.036Z INFO webdriver: DATA { url: 'https://mobitru.com/' }
[2-0] 2025-09-12T15:38:36.230Z INFO webdriver: RESULT null

....

2025-09-12T15:38:37.884Z DEBUG @wdio/local-runner: Runner 2-0 finished with exit code 0
[2-0] PASSED in Android on Android - file:///test/specs/web-appium-demo.js

.....

[3-0] 2025-09-12T15:38:40.190Z INFO webdriver: RESULT null
2025-09-12T15:38:40.310Z DEBUG @wdio/local-runner: Runner 3-0 finished with exit code 0
[3-0] PASSED in Android on Android - file:///test/specs/web-appium-demo.js

....

Spec Files:      4 passed, 4 total (100% completed) in 00:00:44  

2025-09-12T15:38:40.311Z INFO @wdio/local-runner: Shutting down spawned worker
2025-09-12T15:38:40.563Z INFO @wdio/local-runner: Waiting for 0 to shut down gracefully
2025-09-12T15:38:40.563Z INFO @wdio/local-runner: shutting down
2025-09-12T15:38:40.564Z INFO @wdio/cli:launcher: Run onComplete hook

Scroll to Top