Prerequisites

In order to execute tests on Android devices marathon will need Android SDK installed. Devices are expected to be connected to local machine by any means supported by the adb (local usb connection, local emulator or TCP/IP).

CLI

To indicate to CLI that you’re using a vendor config for android you have to specify the type in the root of the Marathonfile configuration as following:

vendorConfiguration:
  type: "Android"
  additional_option1: ...
  additional_option2: ...

Required options

Android SDK path

If you’re using gradle plugin then this option is automatically detected.

If you have an ANDROID_HOME environment variable then this option is automatically detected by the CLI as well.

If this is not the case then you have to specify this option manually:

  • vendorConfiguration:
      type: "Android"
      androidSdk: "/usr/share/local/android"
    

Application APK path

If you’re using gradle plugin then this option is automatically detected. If this is not the case then you have to specify this option manually.

  • vendorConfiguration:
      type: "Android"
      applicationApk: "app/build/outputs/apk/debug/app-debug.apk"
    

Test application APK path

If you’re using gradle plugin then this option is automatically detected. If this is not the case then you have to specify this option manually.

  • vendorConfiguration:
      type: "Android"
      testApplicationApk: "app/build/outputs/apk/androidTest/debug/app-debug.apk"
    

Optional

Automatic granting of permissions

This option will grant all runtime permissions during the installation of the application. This works like the option -g for adb install command. By default, it’s set to false.

  • vendorConfiguration:
      type: "Android"
      autoGrantPermission: true
    
  • marathon {
        autoGrantPermission = true
    }
    
  • marathon {
        autoGrantPermission = true
    }
    

ADB initialisation timeout

This option will allow you to increase/decrease the default adb init timeout of 30 seconds.

  • vendorConfiguration:
      type: "Android"
      adbInitTimeoutMillis: 60000
    
  • marathon {
        adbInitTimeout = 100000
    }
    
  • marathon {
        adbInitTimeout = 100000
    }
    

Device serial number assignment

This option allows to customise how marathon assigns a serial number to devices. Possible values are:

  • automatic
  • marathon_property
  • boot_property
  • hostname
  • ddms
  • vendorConfiguration:
      type: "Android"
      serialStrategy: "automatic"
    
  • marathon {
        serialStrategy = com.malinskiy.marathon.android.serial.SerialStrategy.AUTOMATIC
    }
    
  • marathon {
        serialStrategy = com.malinskiy.marathon.android.serial.SerialStrategy.AUTOMATIC
    }
    

Notes on the source of serial number:

marathon_property - Property name marathon.serialno

boot_property - Property name ro.boot.serialno

hostname - Property name net.hostname

ddms - Adb serial number(same as you see with adb devices command)

automatic - Sequantially checks all available options for first non empty value.

Priority order:

Before 0.6: marathon_property -> boot_property -> hostname -> ddms -> UUID

After 0.6: marathon_property -> ddms -> boot_property -> hostname -> UUID

Install options

By default, these will be -g -r (-r prior to marshmallow). You can specify additional options to append to the default ones.

  • vendorConfiguration:
      type: "Android"
      installOptions: "-d"
    
  • marathon {
        installOptions = "-d"
    }
    
  • marathon {
        installOptions = "-d"
    }
    

Screen recorder configuration

By default, device will record a 1280x720 1Mbps video of up to 180 seconds if it is supported. If on the other hand you want to force screenshots or configure the recording parameters you can specify this as follows:

  • vendorConfiguration:
      type: "Android"
      screenRecordConfiguration:
        preferableRecorderType: "screenshot"
        videoConfiguration:
          enabled: false
          width: 1080
          height: 1920
          bitrateMbps: 2
          timeLimit: 300
        screenshotConfiguration:
          enabled: false
          width: 1080
          height: 1920
          delayMs: 200
    
  • marathon {
        screenRecordConfiguration = ScreenRecordConfiguration(
            com.malinskiy.marathon.device.DeviceFeature.SCREENSHOT,
            VideoConfiguration(
                false, //enabled
                1080, //width
                1920, //height
                2, //Bitrate in Mbps
                300 //Max duration in seconds
            ),
            ScreenshotConfiguration(
                false, //enabled
                1080, //width
                1920, //height
                200 //Delay between taking screenshots
            )
        )
    }
    
  • marathon {
        screenRecordConfiguration = ScreenRecordConfiguration(
            com.malinskiy.marathon.device.DeviceFeature.SCREENSHOT,
            VideoConfiguration(
                false, //enabled
                1080, //width
                1920, //height
                2, //Bitrate in Mbps
                300 //Max duration in seconds
            ),
            ScreenshotConfiguration(
                false, //enabled
                1080, //width
                1920, //height
                200 //Delay between taking screenshots
            )
        )
    }
    

Clear state between test executions

By default, marathon does not clear state between test batch executions. To mitigate potential test side-effects, one could add an option to clear the package data between test runs. Keep in mind that test side-effects might be present. If you want to isolate tests even further, then you should consider reducing the batch size.

  • vendorConfiguration:
      type: "Android"
      applicationPmClear: true
      testApplicationPmClear: true
    
  • marathon {
        applicationPmClear = true
        testApplicationPmClear = true
    }
    
  • marathon {
        applicationPmClear = true
        testApplicationPmClear = true
    }
    

Instrumentation arguments

If you want to pass additional arguments to the am instrument command executed on the device like execute only “SMALL” tests:

  • vendorConfiguration:
      type: "Android"
      instrumentationArgs:
        size: small
    
  • marathon {
        instrumentationArgs { 
            set("size", "small")
        }
    }
    
  • marathon {
        instrumentationArgs { 
            set("size", "small")
        }
    }
    

Allure-kotlin support

If you want to enable on-device collection of allure’s reports, you can use the following option:

  • vendorConfiguration:
      type: "Android"
      allureConfiguration:
        enabled: true
        resultsDirectory: "/sdcard/allure-results"
    
  • marathon {
        allureConfiguration {
            enabled = true
            resultsDirectory = "/sdcard/allure-results"
        }
    }
    
  • marathon {
        allureConfiguration {
            enabled = true
            resultsDirectory = "/sdcard/allure-results"
        }
    }
    

resultsDirectory is the path on the device where allure is outputting it’s data. The default path for allure-kotlin is /sdcard/allure-results. Please refer to allure’s documentation on the usage of allure.

Starting with Android 11 your test application will be required MANAGE_EXTERNAL_STORAGE permission to write allure’s output:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
  ...
</manifest>

Marathon will automatically grant this permission before executing tests if you’re using allure integration

Enabling this option effectively creates two allure reports for each test run:

  • one from the point of view of the marathon test runner
  • one from the point of view of on-device test execution

The on-device report gives you more flexibility and allows you to:

  • Take screenshots whenever you want
  • Divide large tests into steps and visualise them in the report
  • Capture window hierarchy and more.

All allure output from devices will be collected under $output/allure-device-results folder.

Vendor module selection

The first implementation of marathon for Android relied heavily on AOSP’s ddmlib. For a number of technical reasons we had to write our own implementation of the ADB client named adam.

The ddmlib’s implementation is going to be deprecated in marathon 0.7.0 and by default adam is going to be handling all communication with devices.

By 0.8.0, ddmlib is going to be removed completely unless we find major issues.

All the features supported in ddmlib’s implementation transparently work without any changes. We ask you to test adam prior to the removal of ddmlib and submit your concerns/issues.

  • vendorConfiguration:
      type: "Android"
      vendor: ADAM
    
  • marathon {
        vendor = com.malinskiy.marathon.android.VendorType.ADAM
    }
    
  • marathon {
        vendor = com.malinskiy.marathon.android.VendorType.ADAM
    }