Run Maestro tests

Step 1: Prepare an App

You can build your Application .apk file using IDE or in the CLI.

After that, the appropriate file can be found in build/outputs/apk/<profile> directory.

Additional information can be found here.

Step 2: Organize Maestro tests before execution

For uploading your Maestro testing suite, you need to compress your tests into a single .zip archive.
To prevent processing failures, do not use an OS’s graphical interface (such as macOS Finder’s “Compress” option) to create the archive.
This GUI method generates system-specific folders (such as _MACOSX and hidden files) which are incompatible with our system.
The best way is to create an archive using the built-in zip command on macOS or PowerShell/Command Prompt on Windows:

Example of a project with Maestro tests:

Example of commands to create an archive:

MacOS/Linux:

zip -r maestro_tests.zip path/to/directory

Windows:

tar.exe -a -c -f "maesto_tests.zip" "path\to\directory"

Step 3: Upload the App and the archive with tests

Upload your Application and Test Suites apps to Mobitru using our REST API and the generated Access key.

Retrieve and store the id of every uploaded file, because it will be used to trigger an Execution.

Here is an example cURL request to upload the app:

curl --location --request POST 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/v1/spaces/artifacts' \
--header 'x-File-Name: <app_name>.apk' \
--header 'X-Content-Type: application/zip' \
--header 'Authorization: Bearer <ACCESS_KEY>' \
--form 'alias="apk_debug"' \
--form 'file=@"/path/to/app/file/app.apk"' \
--form 'checksum="None"'

Below you can find a sample of the response with an id of the uploaded app:

{
    "id": "d32173ea-ceaf-457b-9fdc-ef7882c0d1ca",
    "name": "6f6a9dbf-5a88-4e22-8c9a-70930e94428f.apk",
    "realName": "<app_name>.apk",
    "bid": "7a21f4ad-e322-43e2-9649-0209de6a9752",
    "wid": "0",
    "private": true,
    "uploadedBy": "<user_name>@test.com",
    "uploadedAt": 1672165595,
    "verified": false,
    "target": "android",
    "contentType": "application/zip",
    "contentLength": 0,
    "href": "quarantine/6f6a9dbf-5a88-4e22-8c9a-70930e94428f.apk",
    "checksum": "None",
    "alias": "<app_name>",
    "apk": null,
    "ipa": null
}


Here is an example cURL request to upload the archive with tests:

curl --location --request POST 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/v1/spaces/artifacts' \
--header 'x-File-Name: <archive_file_name>.zip' \
--header 'X-Content-Type: application/zip' \
--header 'X-Target: maestro' \
--header 'Authorization: Bearer <ACCESS_KEY>' \
--form 'alias="maestro_tests"' \
--form 'file=@"/path/to/archive/file/<archive_file_name>.zip"' \
--form 'checksum="None"'

Below you can find a sample of the response with an id of the uploaded archive:

{
    "id": "420bb311-289b-4745-835a-e9276f17766a",
    "name": "eb3cd115-9a0d-40e0-bed9-7ece5fac6c8c.zip",
    "realName": "<archive_file_name>.zip",
    "bid": "916f0549-4ddc-491a-9fe7-3f27597fd3b7",
    "wid": "0",
    "private": true,
    "uploadedBy": "dfc2813e-d04a-4750-8e61-b8ceaafd8066",
    "uploadedByName": "",
    "uploadedAt": 1782749904,
    "downloadedAt": 1782749904,
    "verified": false,
    "target": "maestro",
    "contentType": "application/zip",
    "contentLength": 9162,
    "href": "quarantine/eb3cd115-9a0d-40e0-bed9-7ece5fac6c8c.zip",
    "bucket": "quarantine",
    "checksum": "None",
    "alias": "maestro_tests",
    "apk": null,
    "ipa": null,
    "attributes": {}
}

Step 4: Find and take device

Find and take appropriate device using our APIs.

Here is an example of cURL request to find a device via API :

curl --location --request GET 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/device/android?model=Pixel 6' \
--header 'Authorization: Bearer <ACCESS_KEY>'

Below you can find a sample of the response with capabilities for found devices:

[
    {
        "desiredCapabilities": {
            "platformName": "Android",
            "platformVersion": "12",
            "deviceName": "GOOGLE Pixel 6a",
            "udid": "26281JEGR04493"
        }
    },
    {
        "desiredCapabilities": {
            "platformName": "Android",
            "platformVersion": "12",
            "deviceName": "GOOGLE Pixel 6",
            "udid": "19161FDF600DJP"
        }
    },
    {
        "desiredCapabilities": {
            "platformName": "Android",
            "platformVersion": "13",
            "deviceName": "GOOGLE Pixel 6 Pro",
            "udid": "1A281FDEE007T3"
        }
    }
]

Here is an example of cURL request to take a device via API:

curl --location --request POST 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/device/26281JEGR04493' \
--header 'Authorization: Bearer <ACCESS_KEY>'

Below you can find a sample of the response with capabilities for the device:

{ 
    "desiredCapabilities": {
        "platformName": "Android",
        "platformVersion": "12",
        "deviceName": "GOOGLE Pixel 6a",
        "udid": "26281JEGR04493"
    }
}

Step 5: Run tests

After taking a Device (in case of a single shard), you can run your Maestro tests using all existing information.

Here is an example of cURL request to run all tests:

curl --location 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/v1/tests/maestro' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <ACCESS_KEY>' \
--data-raw '{
    "device_spec": {
        "serial": "0A071FDD4005QL",
        "platform": "android"
    },
    "app_artifact_id": "<app_artifact_id>",
    "test_artifact_id": "<archive_with_tests_artifact_id>",
    "report": "html"
}'

Below you can find a sample of the response with the Run ID:

{
    "id": "5377e329-b153-4604-a801-70f43f3ce244",
    "engine": "maestro",
    "status": "pending",
    "config": {
        "device_spec": {
            "serial": "0A071FDD4005QL",
            "platform": "android"
        },
        "app_artifact_id": "<app_artifact_id>",
        "test_artifact_id": "<archive_with_tests_artifact_id>",
        "duration": 60,
        "report": "html"
    },
    "summary": "",
    "artifacts": {},
    "created_at": "2026-06-30T15:30:10.800951Z",
    "updated_at": "2026-06-30T15:30:10.800951Z"
}

If necessary, you can cancel pending execution by performing the separate API:

Here is an example of cURL request to cancel the Execution:

curl --location --request PUT 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/v1/tests/maestro/<RUN_ID>/cancel' \
--header 'Authorization: Bearer <ACCESS_KEY>'

As result, you will receive 204 No Content response.

Filter test cases

By default, all tests from the archive will be executed, but it’s possible to use multiple options to filter test cases for execution:

ParameterDescriptionValues
executelist of paths to flow values to execute["path/to/subdirectory/flow1.yaml", "path/to/subdirectory/flow2.yaml"]
include_tagslist of test tags to include in the execution[“include_tag1”, “include_tag2”]
exclude_tagslist of test tags to exclude from the execution[“exclude_tag1”, “exclude_tag2”]
configpath to a config file with full execution configuration (tags, path to flows, etc.)“config/app.yaml”

More details for tags and the config file preparation can be found here.

Here is an example of cURL request for different cases:

curl --location 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/v1/tests/maestro' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <ACCESS_KEY>' \
--data-raw '{
    "device_spec": {
        "serial": "0A071FDD4005QL",
        "platform": "android"
    },
    "app_artifact_id": "<app_artifact_id>",
    "test_artifact_id": "<archive_with_tests_artifact_id>",
    "execute": [
        "cart_flow.yaml",
        "products_list_flow.yaml"
    ],
    "include_tags": [
        "smoke"
    ],
    "exclude_tags": [
        "auth",
        "stagingOnly"
    ]
    "report": "html"
}'

Specify environment properties

By default, no environment properties are used in an execution configuration, but you can provide custom parameters by adding a field (env_vars) to the API request body.
The Field format is “<key>”:”<value>”.

Here is an example of cURL request with custom argument:

curl --location 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/v1/tests/maestro' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <ACCESS_KEY>' \
--data-raw '{
    "device_spec": {
        "serial": "0A071FDD4005QL",
        "platform": "android"
    },
    "app_artifact_id": "<app_artifact_id>",
    "test_artifact_id": "<archive_with_tests_artifact_id>",
 
    "env_vars": {
        "SUCCESS_USER": "testuser@mobitru.com",
        "SUCCESS_PASS": "password1",
        "DEBUG": "true"
    },
    
    "report": "html"
}'

More details on using environment variables in tests can be found here.

Step 6: Get the Run details

After the Execution finishes, you can get the Run details via the API.

Here is an example of cURL a request to get such details:

curl --location --request GET 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/v1/tests/maestro/<RUN_ID>' \
--header 'Authorization: Bearer <ACCESS_KEY>'

Below you can find a sample of the response with artifacts.log ID:

{
    "id": "<RUN_ID>",
    "engine": "maestro",
    "status": "completed",
    "config": {
        "device_spec": {
            "serial": "24131FDEE006R6",
            "platform": "android"
        },
        "app_artifact_id": "<app_artifact_id>",
        "test_artifact_id": "<archive_with_tests_artifact_id>",
        "duration": 60,
        "execute": [
            "cart_flow.yaml",
            "products_list_flow.yaml"
        ],
        "include_tags": [
            "smoke"
        ],
        "exclude_tags": [
            "auth",
            "stagingOnly"
        ],
        "env_vars": {
            "DEBUG": "true",
            "SUCCESS_PASS": "password1",
            "SUCCESS_USER": "testuser@mobitru.com"
        },
        "report": "html"
    },
    "summary": "Test run completed",
    "artifacts": {
        "log": "e16368f3-b1cc-4a89-b616-852e71135669",
        "report": "54067875-4273-4735-860f-1ee66d4baaa8"
    },
    "created_at": "yyyy-mm-ddT19:16:41.598897Z",
    "updated_at": "yyyy-mm-ddT19:16:41.598897Z"
}

Step 7: Download execution report

You can also download a detailed report of the executed tests, which will be retained for up to 10 days after execution.
The report format is determined in the start tests API request by using one of two options in the report field:

  • html – a visually accessible, single-page summary for quick human review of test statuses (Passed, Failed, Skipped)
  • junit – a structured XML document for seamless integration with CI/CD pipelines and third-party test management tools

Here is an example of cURL request to download html log:

curl --output report.html --location 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/v1/spaces/artifacts/<REPORT_ARTIFACT_ID>/download' \
--header 'Authorization: Bearer <ACCESS_KEY>'

Below you can find an example of the downloaded HTML page:

Here is an example of cURL request to download junit log:

curl --output junit_report.xml --location 'https://app.mobitru.com/billing/unit/<BILLING_UNIT>/automation/api/v1/spaces/artifacts/<REPORT_ARTIFACT_ID>/download' \
--header 'Authorization: Bearer <ACCESS_KEY>'

Below you can find an example of the downloaded XML:

<?xml version='1.0' encoding='UTF-8'?>
<testsuites>
  <testsuite name="Test Suite" device="24131FDEE006R6" tests="1" failures="0" time="60.0">
    <testcase id="products_list_flow" name="products_list_flow" classname="products_list_flow" file="products_list_flow.yaml" time="60.0" status="SUCCESS">
      <properties>
        <property name="tags" value="smoke, productsList"/>
      </properties>
    </testcase>
  </testsuite>
</testsuites>

Scroll to Top