Code coverage for End-to-End tests

It’s a Part 3 of Implementing JaCoCo Code Coverage in Android Projects.


The final goal of this step is to create merged Code Coverage for unit tests and E2E tests.

Update module-jacoco.gradle

First you need to set these files in the execution data in module-jacoco.gradle (if you don’t have this file, see Part 1).

        fileTree(dir: "${buildDir}/test-results/instrumentation_results", includes: ['*.ec']),
        fileTree(dir: "${buildDir}/outputs/unit_test_code_coverage", includes: ["**/*.exec", "**/*.ec"])

Complete your workflow

Then fill in the step that runs the tests in Firebase Test Lab with environment-variables and directories-to-pull. Below is a sample step with these parameters.

- name: Run tests on Firebase Test Lab
  run: |-
    gcloud firebase test android run \
      --app="app/build/outputs/apk/debug/app-debug.apk" \
      --test="app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk" \
      --device="model=Pixel2.arm,version=33,locale=en,orientation=portrait" \
      --type=instrumentation \
      --use-orchestrator \
      --test-runner-class="com.appunite.loudius.util.InstrumentationTestRunner" \
      --timeout="20m" \
      --results-dir="${{ steps.generate-dir.outputs.results_dir }}" \
      --results-bucket="${{ steps.generate-dir.outputs.bucket }}" \
      --environment-variables "clearPackageData=true,coverage=true,coverageFilePath=/sdcard/Download/" \
      --directories-to-pull /sdcard/Download

Then download the results from Firebase Test Lab and upload them to the artifact.

- name: Download test results from Firebase Test Lab
  if: always()
  run: |-
    mkdir "app/build/test-results"
    mkdir "app/build/test-results/instrumentation_results"
    gsutil cp -r "gs://${{ steps.generate-dir.outputs.bucket }}/${{ steps.generate-dir.outputs.results_dir }}/Pixel2.arm-33-en-portrait/test_result_1.xml" "app/build/test-results/results.xml"
    gsutil cp -r "gs://${{ steps.generate-dir.outputs.bucket }}/${{ steps.generate-dir.outputs.results_dir }}/Pixel2.arm-33-en-portrait/artifacts/sdcard/Download/*.ec" "app/build/test-results/instrumentation_results"

- name: Upload tests results
  if: always()
  uses: actions/upload-artifact@v4
    name: test-results-instrumentation
    path: |

Now, if you open Google Cloud Console, you should be able to see the .ec files in the Pixel2.arm-33-en-portrait/artifacts/sdcard/Download directory.

gcloud results

And also in the test-results-instrumentation artifact on github.

Merge the results for both, unit tests and E2E tests.

- name: Merge Artifacts
  uses: actions/upload-artifact/merge@v4
    name: test-results
# You should adjust the pattern to the name of your artifacts. Here is test-results-*,
# because ours are test-results-unit and test-results-instrumentation.
    pattern: test-results-*

The last thing you need to do is update the code-coverage job to allow it to download results for both jobs.

  name: Merged code coverage
  runs-on: ubuntu-20.04
    pull-requests: write
    - unit-tests


    - name: Checkout
      uses: actions/checkout@v4

    - name: Download tests results for both jobs
      uses: actions/download-artifact@v4
        name: test-results-unit
        name: test-results

    - name: Run code coverage
      run: ./gradlew codeCoverage

    - name: Store HTML coverage report
      uses: actions/upload-artifact@v4
        name: coverage-report
        path: |

You can check the entire project with JaCoCo implemented and more here.


In this final stage of implementing JaCoCo code coverage in Android projects, you've successfully merged coverage results from unit tests and end-to-end (E2E) tests. With access to merged artifacts and comprehensive coverage reports, you're equipped to assess the quality of your Android application holistically. This setup enables you to identify areas for improvement, enhance test coverage, and ultimately deliver a more reliable and robust product to your users!