Skip to main content

Naming attachments after their test case

Name a screenshot, recording, or log after the test case that produced it, and Bitrise shows it under that test on the Tests tab.

Step versions

This requires the Deploy to Bitrise.io Step version 2.26.0 or newer. If you use the Export test results to Test Reports Step, it must be version 1.3.0 or newer.

You need to:

About the filename structureClick to copy link​

The filename should have the following structure:

<classname>__<name>[__run<k>]__<label>.<ext>

For example, com.example.LoginTest__emptyState__1.png.

To get the correct filename:

  • Copy classname and name from the <testcase> element of your JUnit XML, and replace any of the " * / : < > ? \ | characters with _. Bitrise applies the same replacement to the names in the JUnit XML, so either spelling matches.
  • Always add a label, such as a counter. The label can't contain __ or start with _.
  • If the same tests run on more than one device, put the device in the label, for example api34_1. Otherwise, files with the same name are skipped, and the attachments don't appear.
  • To attach a file to a later run of the same test case, add __run2, __run3, and so on before the label.

Setting up your test toolClick to copy link​

Set up the naming once, in your test configuration. The following examples do this for some popular test tools:

Register a RunListener that takes a screenshot when an Espresso check fails:

// app/build.gradle.kts
android {
defaultConfig {
testInstrumentationRunnerArguments["listener"] = "com.example.testing.BitriseScreenshotListener"
testInstrumentationRunnerArguments["useTestStorageService"] = "true"
}
}

dependencies {
androidTestUtil("androidx.test.services:test-services:1.6.0")
}
// app/src/androidTest/java/com/example/testing/BitriseScreenshotListener.kt
package com.example.testing


private fun clean(value: String) = value.replace(Regex("""["*/:<>?\\|]"""), "_")

class BitriseScreenshotListener : RunListener() {
override fun testStarted(test: Description) {
val default = DefaultFailureHandler(InstrumentationRegistry.getInstrumentation().targetContext)
Espresso.setFailureHandler { error, viewMatcher ->
val screen = Resources.getSystem().displayMetrics.run { "${widthPixels}x$heightPixels" }
val name = "${clean(test.className)}__${clean(test.methodName)}__api${Build.VERSION.SDK_INT}_${screen}_failure"
takeScreenshot().writeToTestStorage(name)
default.handle(error, viewMatcher)
}
}
}

Plain JUnit assertions don't get a screenshot.

Exporting the attachmentsClick to copy link​

Step versions

This requires the Deploy to Bitrise.io Step version 2.26.0 or newer. If you use the Export test results to Test Reports Step, it must be version 1.3.0 or newer.

The Deploy to Bitrise.io Step is always required: it deploys the correctly named attachments alongside your test results. What else you need depends on the Step that runs your tests:

  • Official Bitrise testing Steps: No further configuration is needed. The Deploy to Bitrise.io Step exports the attachments together with the test results. For the list of Steps, see Deploying results from the official Bitrise testing Steps.
  • Other Steps, such as Script or npm Steps: Add the Export test results to Test Reports Step after the Step that runs your tests. It finds the attachments and moves them to the location the Deploy to Bitrise.io Step deploys from. Set its Test result base path input to a folder that contains both your test results and your attachments, for example app/build/. See Using the Export test results to Test Reports Step.

Troubleshooting missing attachmentsClick to copy link​

If an attachment doesn't show up, check the build log:

  • The Export test results to Test Reports Step logs a warning for names that match more than one test or file, or that have an invalid __run number or no label. Other skipped files appear only with verbose logging: set its Enable verbose logging? input to yes.
  • The Deploy to Bitrise.io Step logs a warning for every file in the report that it can't link to a test case.