Running Tests in Docker

When running tests inside Docker containers, you need to extract coverage data from the container to upload it to Qlty. This guide covers two common approaches: using volume mounts and using docker cp.

Method 1: Volume Mounting

Volume mounting is the simplest approach where you mount your project directory into the container, allowing coverage files to be written directly to your host filesystem.

GitHub Actions Example

1name: Main
2on:
3 push:
4 branches: [main]
5 pull_request:
6
7permissions:
8 contents: read
9 id-token: write
10
11jobs:
12 test:
13 runs-on: ubuntu-latest
14 steps:
15 - name: Checkout repo
16 uses: actions/checkout@v4
17
18 - name: Set up Docker Buildx
19 uses: docker/setup-buildx-action@v3
20
21 - name: Build Docker image
22 run: docker build -t myapp-test .
23
24 - name: Run tests in Docker
25 run: |
26 docker run --rm \
27 -v "$(pwd)":/app \
28 -w /app \
29 myapp-test \
30 npm test -- --coverage
31
32 - name: Check coverage file exists
33 run: test -f coverage/lcov.info
34
35 - name: Upload coverage to Qlty
36 uses: qltysh/qlty-action/coverage@v1
37 with:
38 oidc: true
39 files: coverage/lcov.info

Key Points for Volume Mounting

  • Mount your current directory ($(pwd)) to the container’s working directory
  • Use --rm to automatically remove the container after tests complete
  • Coverage files are written directly to your host filesystem
  • Works with any coverage format supported by Qlty

Method 2: Docker Copy

When you can’t use volume mounts (due to security restrictions or container design), you can copy coverage files out of the container after tests complete.

GitHub Actions Example

1name: Main
2on:
3 push:
4 branches: [main]
5 pull_request:
6
7permissions:
8 contents: read
9 id-token: write
10
11jobs:
12 test:
13 runs-on: ubuntu-latest
14 steps:
15 - name: Checkout repo
16 uses: actions/checkout@v4
17
18 - name: Set up Docker Buildx
19 uses: docker/setup-buildx-action@v3
20
21 - name: Build Docker image
22 run: docker build -t myapp-test .
23
24 - name: Run tests in Docker (retain container)
25 run: |
26 docker run --name test-container \
27 -w /app \
28 myapp-test \
29 npm test -- --coverage
30
31 - name: Copy coverage files out of container
32 run: |
33 docker cp test-container:/app/coverage/lcov.info coverage.lcov
34
35 - name: Cleanup container
36 run: docker rm test-container
37
38 - name: Check coverage file exists
39 run: test -f coverage.lcov
40
41 - name: Upload coverage to Qlty
42 uses: qltysh/qlty-action/coverage@v1
43 with:
44 oidc: true
45 files: coverage.lcov

Key Points for Docker Copy

  • Don’t use --rm flag so the container persists after tests
  • Use --name to give the container a predictable name
  • Copy files using docker cp container_name:/path/to/file destination
  • Clean up the container manually after copying files

Alternative CI Providers

Using Coverage Tokens

If you’re not using GitHub Actions with OIDC, replace the upload step with a coverage token:

1- name: Upload coverage to Qlty
2 uses: qltysh/qlty-action/coverage@v1
3 with:
4 token: ${{ secrets.QLTY_COVERAGE_TOKEN }}
5 files: coverage/lcov.info

Manual CLI Upload

For other CI providers, install the Qlty CLI and upload manually:

$# After extracting coverage files from Docker
>curl https://qlty.sh | sh
>qlty coverage publish coverage/lcov.info

For some CI providers you may have to add --override-commit-sha and --override-branch flags with commit SHA and branch names.

$# After extracting coverage files from Docker
>curl https://qlty.sh | sh
>qlty coverage publish coverage/lcov.info --override-commit-sha <COMMIT_SHA> --override-branch <BRANCH_NAME>

Multiple Coverage Files

If your Docker container generates multiple coverage files, you can upload them all:

Volume Mount Approach

1- name: Upload coverage to Qlty
2 uses: qltysh/qlty-action/coverage@v1
3 with:
4 oidc: true
5 files: |
6 coverage/unit.lcov
7 coverage/integration.lcov

Docker Copy Approach

$- name: Copy multiple coverage files
> run: |
> docker cp test-container:/app/coverage/unit.lcov unit.lcov
> docker cp test-container:/app/coverage/integration.lcov integration.lcov

Path Fixing

When running tests in Docker, file paths in coverage reports might not match your repository structure. Use path fixing options:

1- name: Upload coverage to Qlty
2 uses: qltysh/qlty-action/coverage@v1
3 with:
4 oidc: true
5 files: coverage/lcov.info
6 strip-prefix: /app/

Or with the CLI:

$qlty coverage publish --strip-prefix=/app/ coverage/lcov.info

Troubleshooting

Coverage File Not Found

  • Ensure your test command actually generates coverage files
  • Check that the coverage output directory matches your copy/mount paths
  • Verify file permissions allow reading from the container

Path Mismatches

  • Use --strip-prefix to remove container-specific path prefixes
  • Use --add-prefix if you need to add a path prefix
  • Check that source paths in coverage reports match your repository structure

Container Cleanup Issues

  • Always clean up named containers when using docker cp
  • Use docker rm -f container_name to force removal if needed
  • Consider using --rm with volume mounts to avoid cleanup

See Also