title: Jacoco coverage report in gitlab-ci for Android project reports "No class files specified"
body: <p>I set up a Jacoco coverage report for our Kotlin Android project, which is supposed to run in gitlab-ci as job. I followed <a href="https://blog.gouline.net/code-coverage-on-android-with-jacoco-92ec90c9355e" rel="nofollow noreferrer">this article</a> to generate the gradle tasks.
  The coverage report works perfectly if run locally. But if the same gradle task is executed in the gitlab runner, it always produces empty reports with the message "No class files specified".</p>
  
  <p>What's different in the pipeline when it comes to class files?</p>
  
  <p>Maybe one of you is able to spot the issue.</p>
  
  <p><em>jacoco.gradle</em>:</p>
  
  <pre><code>apply plugin: 'jacoco'
  
  android {
      testOptions {
          unitTests.all {
              jacoco {
                  includeNoLocationClasses = true
              }
          }
      }
  
      jacoco {
          version = '0.8.4'
      }
  }
  
  project.afterEvaluate {
      def buildTypes = android.buildTypes.collect { type -&gt;
          type.name
      }
      def productFlavors = android.productFlavors.collect { flavor -&gt;
          flavor.name
      }
      if (!productFlavors) productFlavors.add('')
      productFlavors.each { productFlavorName -&gt;
          buildTypes.each { buildTypeName -&gt;
              def sourceName, sourcePath
              if (!productFlavorName) {
                  sourceName = sourcePath = "${buildTypeName}"
              } else {
                  sourceName = "${productFlavorName}${buildTypeName.capitalize()}"
                  sourcePath = "${productFlavorName}${buildTypeName}"
              }
              def testTaskName = "test${sourceName.capitalize()}UnitTest"
  
              task "${testTaskName}Coverage" (type:JacocoReport, dependsOn: "$testTaskName") {
                  group = "Reporting"
                  description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
                  classDirectories = fileTree(
                      dir: "$project.buildDir/tmp/kotlin-classes/${sourcePath}",
                      excludes: ['**/R.class'] #List of excludes is reduced for this question
                  )
                  def coverageSourceDirs = [
                      "$project.buildDir.parent/src/main/java",
                      "$project.buildDir.parent/src/$productFlavorName/java",
                      "$project.buildDir.parent/src/$buildTypeName/java"
                  ]
  
                  additionalSourceDirs = files(coverageSourceDirs)
                  sourceDirectories = files(coverageSourceDirs)
                  executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec")
  
                  reports {
                      xml.enabled = true
                      html.enabled = true
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p><em>gitlab-ci.yml</em>: (unrelated jobs and stages removed)</p>
  
  <pre><code>image: docker:latest
  
  variables:
      BUILDER_VERSION: "68e9780a"
      GRADLE_ARGS_CI: "--no-daemon --stacktrace"
  
  stages:
      - build
      - test
  
  .build-template: &amp;build_definition
      stage: build
      image: our-docker-registry.com/android-builder:$BUILDER_VERSION
      tags:
          - frontend
      only:
          - merge_requests
          - develop
          - schedules
  
  .test-template: &amp;test_definition
      stage: test
      image: our-docker-registry.com/android-builder:$BUILDER_VERSION
      tags:
          - hermine-frontend
      only:
          - merge_requests
          - develop
          - schedules
  
  build:dev:debug:
      &lt;&lt;: *build_definition
      script:
          - echo "Starting SCRIPT in job $CI_JOB_NAME"
          - ./gradlew $GRADLE_ARGS_CI :app:assembleDevDebug
      artifacts:
          paths:
              - app/build/outputs/apk/dev/debug
              - app/build/tmp/
          expire_in: 1 week
  
  test:dev:debug:
      &lt;&lt;: *test_definition
      script:
          - echo "Starting SCRIPT in job $CI_JOB_NAME"
          - ./gradlew $GRADLE_ARGS_CI -Pci --console=plain :app:testDevDebugUnitTest
          - ./gradlew $GRADLE_ARGS_CI -Pci --console=plain :app:testDevDebugUnitTestCoverage
      artifacts:
          paths:
              - app/build/reports/tests/testDevDebugUnitTest
              - app/build/jacoco #execution file
              - app/build/reports
          expire_in: 1 day
  </code></pre>
  
  <p>Screenshot of my Android Studio <code>build</code> folder:
  <a href="https://i.stack.imgur.com/09dwH.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/09dwH.png" alt="enter image description here"></a></p>