From 9592809e3acd2fe7acec3fd372756264d3545d83 Mon Sep 17 00:00:00 2001 From: Tung Manh Hoang Date: Mon, 8 Dec 2025 20:27:56 +0700 Subject: [PATCH 1/3] KOB-51449 add turbo test appium guide --- .../turbo-test-execution/run-appium-test.adoc | 719 ++++++++++++++++++ 1 file changed, 719 insertions(+) create mode 100644 docs/modules/automation-testing/pages/turbo-test-execution/run-appium-test.adoc diff --git a/docs/modules/automation-testing/pages/turbo-test-execution/run-appium-test.adoc b/docs/modules/automation-testing/pages/turbo-test-execution/run-appium-test.adoc new file mode 100644 index 000000000..059955b93 --- /dev/null +++ b/docs/modules/automation-testing/pages/turbo-test-execution/run-appium-test.adoc @@ -0,0 +1,719 @@ += Run an Appium Turbo Test session +:navtitle: Run an Appium test + +Learn how to run your Appium script with optimal execution speed and minimal latency using Appium Turbo Test Execution. + +== Why Use Turbo Test Execution with Appium + +Kobiton has analyzed thousands of Appium script executions from around the world and found that, on average, *28% of total execution time* is spent on communication between the Appium client and the Appium server. + +This overhead is influenced by factors such as: + +* *Network speed and latency* between the client and server +* *Geographical distance* between where the test runs and where the Appium server is hosted +* *Payload type and frequency*, including screenshots, logs, and element metadata exchanged during each command + +*Turbo Test Execution* minimizes this communication overhead by streamlining the client–server interaction. As a result, your Appium scripts execute *up to 28% faster* on average without requiring any code changes. + +When you use *Xium*, Kobiton’s optimized runtime, instead of *Basic Appium 2*: + +* Tests run *2.23× faster on iOS* +* Tests run *3.34× faster on Android* + +The combination of Turbo Test Execution and Xium delivers a significant reduction in test cycle time – especially valuable for large suites running across multiple devices or CI pipelines. + +== Prepare the test project package + +=== Prerequisites for your automation script + +Turbo Test Execution for Appium supports *XIUM* and *Basic Appium 2* using Appium Java client 9.0.0 or later. + +=== Expose environment variables + +Alter your script to accept these environment variables. Do not hardcode the values of the required variables: + +[cols="1,1,1,1,2",options="header"] +|=== +| Environment variable +| Purpose +| Mapped Appium capability +| Required? +| Behaviour if omitted + +| `KOBITON_URL` +| Appium server URL +| The Appium server URL when you initialize the driver +| *Yes* +| Test run fails. + +| `KOBITON_SESSION` +| Internal capability used by Kobiton to attach test report. +| `kobiton:session` +| *Yes* +| Test report is not available. + +| `KOBITON_UDID` +| UDID of the device under test +| `appium:udid` +| *Yes* +| Test run fails. + +| `KOBITON_USERNAME` +| Kobiton username +| `appium:username` +| *Yes* +| Test run fails. + +| `KOBITON_APIKEY` +| Kobiton API Key +| `appium:accessKey` +| *Yes* +| Test run fails. + +| `KOBITON_APP` +| App to test +| `appium:app` +| No +| Manually set `appium:app` in your capabilities, or remove to test web apps. + +| `KOBITON_RUNTIME` +| Determines whether to run a Basic Appium 2 or Xium script +| `kobiton:runtime` +| No +| Manually set `kobiton:runtime` in your capabilities. + +| `KOBITON_SESSION_NAME` +| Name of the test session +| `kobiton:sessionName` +| No +| Manually set `kobiton:sessionName` in your capabilities. + +| `KOBITON_SESSION_DESCRIPTION` +| Description for the test session +| `kobiton:sessionDescription` +| No +| Manually set `kobiton:sessionDescription` in your capabilities. +|=== + +=== Specify location for test artifacts + +Configure your test script so that artifacts generated from the test run are placed in the `output` directory of the project’s root folder. This ensures that the artifacts can be downloaded from the test report after running. + +NOTE: A future update of Turbo Test will create this `output` directory automatically. + +[source,java] +---- + // Create output directory +try { + Files.createDirectories(Path.of("output")); +} catch (IOException ignored) { +} + +// Write logs to a test_log.txt file under output +try (FileWriter log = new FileWriter("output/test_log.txt", true)) { + log.write("=== TurboTest Run Started ===\n"); + log.write("Timestamp: " + LocalDateTime.now() + "\n"); +} ... +---- + +== Full example scripts + +=== UIAutomator2 (Android) + +[source,java] +---- +public class SimpleTurboTest { + public static void main(String[] args) { + + try { + Files.createDirectories(Path.of("output")); + } catch (IOException ignored) { + } + + try (FileWriter log = new FileWriter("output/test_log.txt", true)) { + log.write("=== TurboTest Run Started ===\n"); + log.write("Timestamp: " + LocalDateTime.now() + "\n"); + + // Required environment variables + String kobitonUrl = System.getenv("KOBITON_URL"); + String udid = System.getenv("KOBITON_UDID"); + String kobitonSession = System.getenv("KOBITON_SESSION"); + String kobitonUsername = System.getenv("KOBITON_USERNAME"); + String kobitonApiKey = System.getenv("KOBITON_APIKEY"); + + // Optional environment variables + String app = System.getenv("KOBITON_APP"); + String sessionName = System.getenv("KOBITON_SESSION_NAME"); + String sessionDescription = System.getenv("KOBITON_SESSION_DESCRIPTION"); + String kobitonRuntime = System.getenv("KOBITON_RUNTIME"); + + // Validate env vars + if (webdriverUrl == null || kobitonSession == null || udid == null || + webdriverUrl.isEmpty() || kobitonSession.isEmpty() || udid.isEmpty()) { + System.err.println("Missing required env vars: KOBITON_UDID, KOBITON_WEBDRIVER_URL, or KOBITON_SESSION"); + return; + } + + // Provide default values for optional env vars if null or empty + if (app == null || app.isEmpty()) { + app = "https://example.com/downloads/sample.apk"; + } + + if (sessionName == null || sessionName.isEmpty()) { + sessionName = "A Turbo Test session for Android"; + } + + if (sessionDescription == null || kobitonUsername.isEmpty()) { + sessionDescription = "A sample Turbo Test session for Android"; + } + + // Capabilities + DesiredCapabilities caps = new DesiredCapabilities(); + caps.setCapability("kobiton:sessionName", sessionName); + caps.setCapability("kobiton:sessionDescription", sessionDescription); + caps.setCapability("appium:udid", udid); + caps.setCapability("appium:app", app); + caps.setCapability("appium:automationName", "UIAutomator2"); + caps.setCapability("kobiton:session", kobitonSession); + caps.setCapability("appium:username", kobitonUsername); + caps.setCapability("appium:accessKey", kobitonApiKey); + caps.setCapability("kobiton:runtime", kobitonRuntime); + + // Initialize driver + AndroidDriver driver = new AndroidDriver(new URI(kobitonBaseUrl).toURL(), caps); + + // Save page source + Files.writeString(Path.of("output/page_source.xml"), driver.getPageSource()); + + // Screenshot + File shot = driver.getScreenshotAs(OutputType.FILE); + Files.copy(shot.toPath(), Path.of("output/screenshot.png"), StandardCopyOption.REPLACE_EXISTING); + log.write("Screenshot saved\n"); + + driver.quit(); + log.write("Completed successfully at " + LocalDateTime.now() + "\n"); + + driver.quit(); + + } catch (Exception e) { + try (FileWriter err = new FileWriter("output/error.log", true)) { + err.write("Exception: " + e.getMessage() + "\n"); + e.printStackTrace(new PrintWriter(err)); + } catch (IOException ignored) {} + e.printStackTrace(); + } + } +} +---- + +=== XCUITest (iOS) + +[source,java] +---- +public class SimpleTurboTest { + public static void main(String[] args) { + + try { + Files.createDirectories(Path.of("output")); + } catch (IOException ignored) { + } + + try (FileWriter log = new FileWriter("output/test_log.txt", true)) { + log.write("=== TurboTest Run Started ===\n"); + log.write("Timestamp: " + LocalDateTime.now() + "\n"); + + // Required environment variables + String kobitonUrl = System.getenv("KOBITON_URL"); + String udid = System.getenv("KOBITON_UDID"); + String kobitonSession = System.getenv("KOBITON_SESSION"); + String kobitonUsername = System.getenv("KOBITON_USERNAME"); + String kobitonApiKey = System.getenv("KOBITON_APIKEY"); + + // Optional environment variables + String app = System.getenv("KOBITON_APP"); + String sessionName = System.getenv("KOBITON_SESSION_NAME"); + String sessionDescription = System.getenv("KOBITON_SESSION_DESCRIPTION"); + String kobitonRuntime = System.getenv("KOBITON_RUNTIME"); + + // Validate env vars + if (webdriverUrl == null || kobitonSession == null || udid == null || + webdriverUrl.isEmpty() || kobitonSession.isEmpty() || udid.isEmpty()) { + System.err.println("Missing required env vars: KOBITON_UDID, KOBITON_WEBDRIVER_URL, or KOBITON_SESSION"); + return; + } + + // Provide default values for optional env vars if null or empty + if (app == null || app.isEmpty()) { + app = "https://example.com/downloads/sample.ipa"; + } + + if (sessionName == null || sessionName.isEmpty()) { + sessionName = "A Turbo Test session for iOS"; + } + + if (sessionDescription == null || kobitonUsername.isEmpty()) { + sessionDescription = "A sample Turbo Test session for iOS"; + } + + // Capabilities + DesiredCapabilities caps = new DesiredCapabilities(); + caps.setCapability("kobiton:sessionName", sessionName); + caps.setCapability("kobiton:sessionDescription", sessionDescription); + caps.setCapability("appium:udid", udid); + caps.setCapability("appium:app", app); + caps.setCapability("appium:automationName", "XCUITest"); + caps.setCapability("kobiton:session", kobitonSession); + caps.setCapability("appium:username", kobitonUsername); + caps.setCapability("appium:accessKey", kobitonApiKey); + caps.setCapability("kobiton:runtime", kobitonRuntime); + + // Initialize driver + IOSDriver driver = new IOSDriver(new URI(kobitonUrl).toURL(), caps); + + // Save page source + Files.writeString(Path.of("output/page_source.xml"), driver.getPageSource()); + + // Screenshot + File shot = driver.getScreenshotAs(OutputType.FILE); + Files.copy(shot.toPath(), Path.of("output/screenshot.png"), StandardCopyOption.REPLACE_EXISTING); + log.write("Screenshot saved\n"); + + driver.quit(); + log.write("Completed successfully at " + LocalDateTime.now() + "\n"); + + driver.quit(); + + } catch (Exception e) { + try (FileWriter err = new FileWriter("output/error.log", true)) { + err.write("Exception: " + e.getMessage() + "\n"); + e.printStackTrace(new PrintWriter(err)); + } catch (IOException ignored) {} + e.printStackTrace(); + } + } +} +---- + +=== Package the test project + +Run your tests locally to verify they work. + +Package the project into a `.zip` that contains the compiled `.jar` and all runtime dependencies. + +Name the archive, e.g., `test_runner.zip`. + +== Upload test runner + +=== Method 1: Using Kobiton Portal + +Log in to the Kobiton Portal using your Kobiton username/email and password. + +Navigate to the Device list by selecting *Devices* on the navigation pane. + +Select the 3-dot icon on the Android device you plan to use for testing. + +image::PLACEHOLDER_image_1[] + +Select *Automation Settings*. + +image::PLACEHOLDER_image_2[] + +In the Framework dropdown, select *UIAutomator/ Espresso* or *XCUITest*. + +image::PLACEHOLDER_image_3[] + +Scroll down until you find the Test Runner section, then select *Upload Test Runner*. + +image::PLACEHOLDER_image_4[] + +Choose the _test_runner.zip_ file and select *Open*. + +When the file finishes uploading, note down the value of *Test Runner Url*. This is the `` to be used later. + +image::PLACEHOLDER_image_5[] + +=== Method 2: Using Kobiton API + +Run the following API endpoints, in order, to upload the test runner to Kobiton: + +* https://api.kobiton.com/v2/docs#tag/NativeFrameworkAPI/operation/NativeFrameworkAPI_GetTestRunnerUploadUrl[Get test runner upload URL] +* https://api.kobiton.com/v2/docs#tag/ApplicationAPI/operation/CustomAPIv2_ApplicationAPI_UploadFileToS3[Upload file to S3] (use the value of `upload_url` from _Get test runner upload URL_) +* https://api.kobiton.com/v2/docs#tag/NativeFrameworkAPI/operation/NativeFrameworkAPI_GetTestRunnerUploadUrl[Get test runner download URL] (use the value of `path` from _Get test runner download URL_) + +Note down the value of `url` and `test_runner_id` from the response of the _Get test runner download URL_ endpoint. Either of these values can be the `` to be used later. + +NOTE: The `url` (test runner download URL) expires after about 12 hours. It is recommended to use the `test_runner_id` (test runner ID) as it does not expire. + +== Obtain Kobiton API credentials + +Log in to the Kobiton Portal using your Kobiton username/email and password. + +Select the *Help* icon, then choose *API*. + +image::PLACEHOLDER_image_6[] + +You will be taken to the API documentation home page. Note down the value of *Base URL (Rest)* as it is the `` to be used later. + +image::PLACEHOLDER_image_7[] + +Go back to the Kobiton Portal and note down the value of one of the https://docs.kobiton.com/profile/manage-your-api-credentials#_get_an_api_key[API Keys]. This value, together with the Kobiton account’s username/email, is required to obtain the `` to be used later. Add a new key if there aren’t any. + +image::PLACEHOLDER_image_8[] + +== Run the automation test + +Open a terminal and run the following command. Replace placeholder values with your own. + +[source,bash] +---- +curl --location '/v2/sessions/native' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic ' \ +--data '{ + "test_framework": "", + "test_runner": "", + "session_name": "", + "session_description": "", + "app": "", + "udid": "", + "device_name": "", + "tags": , + "platform_version": "", + "env": {}, + "args": [], + "run_command": "", + "execution_mode": "", + "device_wait_timeout": , +}' +---- + +The system finds the first *Private device* that matches ``, then ``, and then ``. It then runs the test script on the device. + +NOTE: Appium Turbo Test execution is not available for Public devices. + +If the request is successful, the response is similar to the below: + +* If `execution_mode` is `IMMEDIATE`: + +[source,json] +---- +{ + "session_id": , + "device_udid": "", + "device_id": , + "request_id": "", + "test_report_download_url": "" +} +---- + +* If `execution_mode` is `QUEUED`: + +[source,json] +---- +{ + "queue_id": "", + "requested_at": "", + "query_params": { + "query_param_1": "value" + } +} +---- + +See the next sections for request and response parameter reference. + +=== API authentication reference + +* `` +** *Type:* string +** *Required:* Yes +** *Example:* `https://api.kobiton.com` +** *Description:* API base URL + +* `` +** *Type:* string +** *Required:* Yes +** *Example:* `a29iaXRvbmFkbWluOjI4Nzk4MTI0LTItZGEtd2Rhdy0tNDMtMjQzMjQ=` +** *Description:* Base64-encoded `username_or_email:api_key` + +=== Request parameter reference + +* `test_framework` +** *Type:* enum +** *Required:* Yes +** *Example:* `APPIUM`, `XIUM` +** *Description:* Use `APPIUM` to run Basic Appium 2 script or use `XIUM` to run XIUM script +** *Note:* requires `KOBITON_RUNTIME` environment variable + +* `test_runner` +** *Type:* string +** *Required:* Yes +** *Example:* either of the below: +*** `https://kobiton-*.s3.amazonaws.com/test-runner/users/17/test_runner-xyz.zip` +*** `f8b6967d-1975-4c08-92b7-037512416127` +** *Description:* Can be either of the below: +*** Download URL of the test runner +*** The unique ID of the test runner + +* `session_name` +** *Type:* string +** *Required:* No +** *Example:* `A Turbo Test session` +** *Description:* The display name of the session +** *Note:* requires `KOBITON_SESSION_NAME` environment variable. + +* `session_description` +** *Type:* string +** *Required:* No +** *Example:* `A Turbo Test session on Android` +** *Description:* The description of the session +** *Note:* requires `KOBITON_SESSION_DESCRIPTION` environment variable. + +* `app` +** *Type:* string +** *Required:* No +** *Example:* `kobiton-store:v34321`, `https://example.com/downloads/sample.ipa` +** *Description:* The app to test. +** *Note:* requires `KOBITON_APP` environment variable. + +* `udid` +** *Type:* string +** *Required:* Yes if `tags` and `device_name` is not provided +** *Example:* `8bf2c82a` +** *Description:* UDID of the Kobiton Private device + +* `device_name` +** *Type:* string +** *Required:* Yes if `tags` and `udid` is not provided +** *Example:* `Pixel 8`, `iPad *`, `*` +** *Description:* Name of the Kobiton Private device. Wildcard (`*`) is supported. + +* `platform_version` +** *Type:* string +** *Required:* No +** *Example:* `12` +** *Description:* OS version of the device + +* `tags` +** *Type:* array of strings +** *Required:* Yes if `udid` and `device_name` is not provided +** *Example:* `[[ "healthy" ], [ "project", "dev" ]]` +** *Description:* Tags to filter Private devices. Follow the below formats: +*** Single group with a single tag: `[[ "healthy" ]]` (Only select devices with `healthy` tag) +*** Single group with multiple tags (OR within group): `[[ "project", "dev" ]]` (Select devices with either `project` or `dev` tag) +*** Multiple groups (AND across groups): `[[ "healthy" ], [ "project", "dev" ]]` (Select devices with `healthy` and either `project` or `dev` tag) + +* `env` +** *Type:* object (string keys and values) +** *Required:* No +** *Example:* `{ "VARIABLE_1": "value1", "VARIABLE_2": "value2" }` +** *Description:* Additional environment variables to export + +* `args` +** *Type:* array of strings +** *Required:* No +** *Example:* `[ "--arg value", "--another-arg value2" ]` +** *Description:* Additional command-line arguments for your test + +* `run_command` +** *Type:* string +** *Required:* Yes +** *Example:* `java -jar SimpleTurboTest.jar` +** *Description:* Command that runs the compiled `.jar` file of your script. Includes all command arguments here. + +* `execution_mode` +** *Type:* enum +** *Required:* No +** *Values:* `IMMEDIATE` (default) or `QUEUED` +** *Description:* Specify whether the test should be executed immediately or in a queue. +*** `IMMEDIATE`: test executes immediately if the device is available. If there is no device available, the test terminates. +*** `QUEUED`: test is put in a queue waiting for execution. If system cannot find an available device after the timeout period, the test terminates. + +* `device_wait_timeout` +** *Type:* integer (in seconds) +** *Condition:* only applies when `execution_mode` is `QUEUED` +** *Required:* No +** *Default value:* `900` – *Minimum:* `1` – *Maximum:* `86400` +** *Example:* `20` +** *Description:* The timeout period for queued execution mode. If system cannot find an available device after the timeout period, the test terminates. + +=== Response parameter reference + +==== Immediate execution mode + +* `session_id` +** *Type:* integer +** *Example:* `1135` +** *Description:* ID of the session where the test executed. Use this ID to query the session details. + +* `device_udid` +** *Type:* string +** *Example:* `5***1FDCH730X1` +** *Description:* UDID of the device under test. Use this to find the session. + +* `device_id` +** *Type:* integer +** *Example:* `31234` +** *Description:* ID of the device under test. Use this ID to query the device details. + +* `request_id` +** *Type:* string +** *Example:* `d8c22b16-e863-47ed-b2b5-c1103c4a91a0` +** *Description:* Appium request ID of the test run. *Note:* this is *not* Kobiton session ID. + +* `test_report_download_url` +** *Type:* string +** *Example:* `https://kobiton-acme.s3.amazonaws.com/organizations/6/sessions/d8c22b16-e863-47ed-b2b5-c1103c4a91a0/test-report.zip` +** *Description:* URL to download the test report. Only downloadable after the test has finished. + +==== Queued execution mode + +* `queue_id` +** *Type:* string +** *Example:* `5a035e50-7032-4396-89ee-78428e8e3a9e` +** *Description:* ID of the queue. Use this value to query the status of the test execution in the queue. + +* `requested_at` +** *Type:* datetime (UTC) +** *Example:* `2025-11-05T04:52:32.871Z` +** *Description:* UTC date and time when the request is made. + +* `query_params` +** *Type:* object +** *Description:* The body of the request for reference. + +=== Check status for queued execution mode + +For requests made with queued execution mode, run the following command in a terminal to check the status. Replace placeholder values with your own. + +[source,bash] +---- +curl --location '/v2/sessions/queue/' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic ' +---- + +* `` is obtained from the response of the request. + +The response is similar to that of the test run request, with 2 additional parameters: + +* `status` +** *Type:* enum +** *Values:* +*** `QUEUED`: the test is still waiting to be executed +*** `TIMED_OUT`: the test timed out before an available device can be found +*** `INITIATED`: the test is executed +** *Description:* Status of the execution. + +* `session_id` +** *Type:* integer +** *Condition:* this value is only returned when `status` is `INITIATED` +** *Example:* `1135` +** *Description:* ID of the session where the test executed. Use this ID to query the session details. + +== Download test report + +=== Method 1: Using Kobiton Portal + +Log in to the Kobiton Portal using your Kobiton username/email and password. + +Navigate to *Sessions*, then find a session associated with the target device of the test. You can enter `` in the session search box to quickly filter sessions. + +Select the session in the search results to navigate to Session Overview. + +Under *Test Report*, select *Download* to save the test report to your computer. *Note*: The test report can only be downloaded for sessions with the status: *Complete*. + +=== Method 2: Using Kobiton API + +For immediate execution mode, the report download URL is available in the response of the automation test run request. + +*Note:* the test report download URL expires after about 12 hours. To obtain a new test report download URL, follow the same steps for queued execution mode below. + +For queued execution mode, run the below command in the terminal to retrieve the test report download URL. Replace placeholder values with your own. + +[source,bash] +---- +curl --location '/v2/sessions/' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic ' +---- + +* `` is obtained from the response of the <> request. + +The test report download URL is the value of `test_report_url` in the response. *Note:* if the `test_report_url` is not available, wait until the test has finished executing before trying again. + +== Sample demo script + +Download and extract the https://kobiton-software.s3.us-east-1.amazonaws.com/v4.21.2/TurboTest_updated.zip[sample demo script]. + +The sample includes three main folders: + +* *TurboTestAndroid* – Contains scripts for Android devices. +* *TurboTestiOS* – Contains scripts for iOS devices. +* *artifacts* – Contains the precompiled `.jar` and `.zip` files for both Android and iOS. + +=== Use the precompiled test runners + +You can use the provided test runners to run a Turbo Test Session. + +* Locate the test runners at `artifacts/test_runners.zip`. This file includes `.jar` files for both Android and iOS tests. +* Upload the test runners to Kobiton and obtain the test runner download URL or test runner ID. +* Find a device in Kobiton and note down its UDID. +* Find an app to test and note down its Kobiton store ID or download URL. +* Make the following API requests in your terminal after updating the placeholders with your values. You can change `execution_mode` to `QUEUED` to queue multiple tests. + +**Android:** + +[source,bash] +---- +curl --location '/v2/sessions/native' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic ' \ +--data '{ + "test_framework": "XIUM", + "test_runner": "", + "session_name": "A Turbo Test session on Android", + "session_description": "A session to demo the features of Turbo Test on Android", + "app": , + "udid": "", + "run_command": "java -jar TurboTestAndroid.jar", + "execution_mode": "IMMEDIATE" +}' +---- + +**iOS:** + +[source,bash] +---- +curl --location '/v2/sessions/native' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic ' \ +--data '{ + "test_framework": "APPIUM", + "test_runner": "", + "session_name": "A Turbo Test session on iOS", + "session_description": "A session to demo the features of Turbo Test on iOS", + "app": , + "udid": "", + "run_command": "java -jar TurboTestiOS.jar", + "execution_mode": "IMMEDIATE" +}' +---- + +* Download the test report from the URL in the response. +** If `execution_mode` is `QUEUED`, follow the instructions from the <> section to obtain the test report. +* The test report should contain: +** A `stdout.log` file that captures the output of the run command. +** A `stderr.log` file that captures the error(s) when executing the run command, if any. +** An `output` folder that contains the test log, XML page source, and screenshot of the app under test. + +=== Modify and recompile scripts + +You can modify the test scripts to fit your testing needs. After making changes: + +* Recompile the `.jar` files. +* Package them as `.zip` test runners. +* Upload the updated test runners to Kobiton. + +== Limitation + +* Mixed sessions are not supported for Appium Turbo Test. From b6aceca8bd7302269d3b7697f24aec7f7a6c94fe Mon Sep 17 00:00:00 2001 From: Tung Manh Hoang Date: Wed, 17 Dec 2025 11:14:31 +0700 Subject: [PATCH 2/3] KOB-51449 add instructions to obtain api base url --- docs/modules/profile/images/api-base-url.png | Bin 0 -> 33029 bytes docs/modules/profile/images/help-portal-api.png | Bin 0 -> 11846 bytes .../pages/manage-your-api-credentials.adoc | 10 +++++++--- .../profile/pages/manage-your-profile.adoc | 10 +++++++++- .../profile/partials/obtain-api-base-url.adoc | 9 +++++++++ 5 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 docs/modules/profile/images/api-base-url.png create mode 100644 docs/modules/profile/images/help-portal-api.png create mode 100644 docs/modules/profile/partials/obtain-api-base-url.adoc diff --git a/docs/modules/profile/images/api-base-url.png b/docs/modules/profile/images/api-base-url.png new file mode 100644 index 0000000000000000000000000000000000000000..400b86551017e5ef20ef2f69eeb76c4db75f7f1e GIT binary patch literal 33029 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 ON{P#hRf`z>{l5V0P?a?R literal 0 HcmV?d00001 diff --git a/docs/modules/profile/images/help-portal-api.png b/docs/modules/profile/images/help-portal-api.png new file mode 100644 index 0000000000000000000000000000000000000000..b5e49977b437e0161c83205c8c2af715d3806a78 GIT binary patch literal 11846 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 wOx>^l(3;SRPcw*>j(K9 Date: Wed, 17 Dec 2025 16:26:48 +0700 Subject: [PATCH 3/3] KOB-51449 add introductions and prerequisites for turbo test appium --- docs/modules/automation-testing/nav.adoc | 1 + .../turbo-test-execution/run-appium-test.adoc | 84 ++++++++++++------- .../run-game-driver-test.adoc | 2 +- .../pages/manage-your-api-credentials.adoc | 1 + 4 files changed, 57 insertions(+), 31 deletions(-) diff --git a/docs/modules/automation-testing/nav.adoc b/docs/modules/automation-testing/nav.adoc index 3691eda70..482df0221 100644 --- a/docs/modules/automation-testing/nav.adoc +++ b/docs/modules/automation-testing/nav.adoc @@ -42,6 +42,7 @@ * Turbo Test Execution (_beta_) ** xref:automation-testing:turbo-test-execution/run-game-driver-test.adoc[] +** xref:automation-testing:turbo-test-execution/run-appium-test.adoc[] * Generate Appium test reports ** xref:automation-testing:generate-appium-test-reports/html-reports-for-appium-c-sharp.adoc[] diff --git a/docs/modules/automation-testing/pages/turbo-test-execution/run-appium-test.adoc b/docs/modules/automation-testing/pages/turbo-test-execution/run-appium-test.adoc index 059955b93..964bfbae1 100644 --- a/docs/modules/automation-testing/pages/turbo-test-execution/run-appium-test.adoc +++ b/docs/modules/automation-testing/pages/turbo-test-execution/run-appium-test.adoc @@ -1,8 +1,23 @@ -= Run an Appium Turbo Test session += Run an Appium Turbo test :navtitle: Run an Appium test +[NOTE] +==== +This feature is currently in Beta and is limited to Private devices. +==== + Learn how to run your Appium script with optimal execution speed and minimal latency using Appium Turbo Test Execution. +After reading this document, you will be able to: + +* Modify your existing Appium automation script to make it compatible with Appium Turbo Test. + +* Package your script into a test runner and upload it to Kobiton. + +* Make a request to the Kobiton API v2 to execute the Appium Turbo test with the uploaded test runner. + +* Retrieve the test result and other test artifacts. + == Why Use Turbo Test Execution with Appium Kobiton has analyzed thousands of Appium script executions from around the world and found that, on average, *28% of total execution time* is spent on communication between the Appium client and the Appium server. @@ -13,7 +28,7 @@ This overhead is influenced by factors such as: * *Geographical distance* between where the test runs and where the Appium server is hosted * *Payload type and frequency*, including screenshots, logs, and element metadata exchanged during each command -*Turbo Test Execution* minimizes this communication overhead by streamlining the client–server interaction. As a result, your Appium scripts execute *up to 28% faster* on average without requiring any code changes. +*Turbo Test Execution* minimizes this communication overhead by streamlining the client–server interaction.As a result, your Appium scripts execute *up to 28% faster* on average without requiring any code changes. When you use *Xium*, Kobiton’s optimized runtime, instead of *Basic Appium 2*: @@ -22,11 +37,34 @@ When you use *Xium*, Kobiton’s optimized runtime, instead of *Basic Appium 2*: The combination of Turbo Test Execution and Xium delivers a significant reduction in test cycle time – especially valuable for large suites running across multiple devices or CI pipelines. -== Prepare the test project package +[#_prerequisites] +== Prerequisites + +* A Kobiton account.Note down the below information: -=== Prerequisites for your automation script +** xref:profile:manage-your-profile.adoc#_view_your_username_and_email[Username or email,window=read-later] -Turbo Test Execution for Appium supports *XIUM* and *Basic Appium 2* using Appium Java client 9.0.0 or later. +** xref:profile:manage-your-api-credentials.adoc#_obtain_the_api_base_url[API base URL,window=read-later] + +** xref:profile:manage-your-api-credentials.adoc#_get_an_api_key[API Key,window=read-later] + +* Private devices available in the Kobiton account. + +* An Appium automation script that satisfies the below prerequisites. + ++ + +[cols="1,1"] +|=== +|Language |Additional requirements +|Java | Compatible with `java-client` 9.0.0 or newer. +|=== + ++ + +NOTE: Contact Kobiton support if you want additional languages or frameworks supported. + +== Prepare the test project package === Expose environment variables @@ -312,25 +350,27 @@ Navigate to the Device list by selecting *Devices* on the navigation pane. Select the 3-dot icon on the Android device you plan to use for testing. -image::PLACEHOLDER_image_1[] +image:automation-testing:open-device-overview-context.png[width="1000",alt="Navigate to Devices and select the 3-dot icon on an Android device"] Select *Automation Settings*. -image::PLACEHOLDER_image_2[] +image:automation-testing:device-overview-closeup.png[width="1000",alt="Note down the device UDID, then select Automation Settings"] In the Framework dropdown, select *UIAutomator/ Espresso* or *XCUITest*. -image::PLACEHOLDER_image_3[] +image:automation-testing:automation-framework-uiautomator-espresso.png[width="1000",alt="Select UIAutomator or Espresso"] Scroll down until you find the Test Runner section, then select *Upload Test Runner*. -image::PLACEHOLDER_image_4[] +image:automation-testing:upload-test-runner.png[width="1000",alt="Select Upload Test Runner under the Test Runner section"] Choose the _test_runner.zip_ file and select *Open*. When the file finishes uploading, note down the value of *Test Runner Url*. This is the `` to be used later. -image::PLACEHOLDER_image_5[] +image:automation-testing:test-runner-url.png[width="500",alt="Note down the value of Test Runner URL"] + +NOTE: The Test Runner URL expires after about 12 hours. === Method 2: Using Kobiton API @@ -344,22 +384,6 @@ Note down the value of `url` and `test_runner_id` from the response of the _Get NOTE: The `url` (test runner download URL) expires after about 12 hours. It is recommended to use the `test_runner_id` (test runner ID) as it does not expire. -== Obtain Kobiton API credentials - -Log in to the Kobiton Portal using your Kobiton username/email and password. - -Select the *Help* icon, then choose *API*. - -image::PLACEHOLDER_image_6[] - -You will be taken to the API documentation home page. Note down the value of *Base URL (Rest)* as it is the `` to be used later. - -image::PLACEHOLDER_image_7[] - -Go back to the Kobiton Portal and note down the value of one of the https://docs.kobiton.com/profile/manage-your-api-credentials#_get_an_api_key[API Keys]. This value, together with the Kobiton account’s username/email, is required to obtain the `` to be used later. Add a new key if there aren’t any. - -image::PLACEHOLDER_image_8[] - == Run the automation test Open a terminal and run the following command. Replace placeholder values with your own. @@ -398,9 +422,9 @@ If the request is successful, the response is similar to the below: [source,json] ---- { - "session_id": , + "session_id": "", "device_udid": "", - "device_id": , + "device_id": "", "request_id": "", "test_report_download_url": "" } @@ -427,13 +451,13 @@ See the next sections for request and response parameter reference. ** *Type:* string ** *Required:* Yes ** *Example:* `https://api.kobiton.com` -** *Description:* API base URL +** *Description:* The API base URL. * `` ** *Type:* string ** *Required:* Yes ** *Example:* `a29iaXRvbmFkbWluOjI4Nzk4MTI0LTItZGEtd2Rhdy0tNDMtMjQzMjQ=` -** *Description:* Base64-encoded `username_or_email:api_key` +** *Description:* Base64-encoded `username_or_email:api_key`. === Request parameter reference diff --git a/docs/modules/automation-testing/pages/turbo-test-execution/run-game-driver-test.adoc b/docs/modules/automation-testing/pages/turbo-test-execution/run-game-driver-test.adoc index 72d8b869b..13363a4c8 100644 --- a/docs/modules/automation-testing/pages/turbo-test-execution/run-game-driver-test.adoc +++ b/docs/modules/automation-testing/pages/turbo-test-execution/run-game-driver-test.adoc @@ -1,4 +1,4 @@ -= Run a GameDriver test on Kobiton += Run a GameDriver test :navtitle: Run a GameDriver test [NOTE] diff --git a/docs/modules/profile/pages/manage-your-api-credentials.adoc b/docs/modules/profile/pages/manage-your-api-credentials.adoc index e76992414..80fc61ffd 100644 --- a/docs/modules/profile/pages/manage-your-api-credentials.adoc +++ b/docs/modules/profile/pages/manage-your-api-credentials.adoc @@ -3,6 +3,7 @@ Learn how to manage your API keys and server URL so you can add them to your xref:automation-testing:scripting/auto-generate-an-appium-script.adoc[Appium scripts] and xref:integrations:index.adoc[integration] configuration files. +[#_obtain_the_api_base_url] == Obtain the API base URL include::partial$obtain-api-base-url.adoc[]