Search code examples
pythonpytestgithub-actionscode-coveragecoveralls

Coveralls code coverage badge giving 0% code coverage using Pytest and GitHub Actions (Python)


Similar question but unfortunately no clear answer: here

I've been trying to get pytest, which runs during my GitHub Actions CI, to produce a code coverage badge on my readme.md.

My approach was:

  1. Use pytest Source/tests -v --cov to generate a .coverage file at the root.
  2. Use coveragepy-lcov --data_file_path .coverage --output_file_path lcov.info to convert this .coverage file into lcov.info which is also at the root, using this tool
  3. In the main.yml for GitHub actions, add, to the jobs: build: steps: section
      - name: Upload Coverage Results
        uses: coverallsapp/github-action@master
        with:
          github-token: ${{ secrets.github_token }}
          path-to-lcov: lcov.info

The build passed but results in 0% code coverage. I don't know why. Locally my code has ~90% code coverage. You can see the coveralls page for my build here. The repo is here.

In addition to this problem, I also ran into another. When I add the pytest and coveragepy-lcov commands to the main.yml file (see below) then GitHub Actions fails out at the install stage of the coveragepy-lcov library:

Run pip install coveragepy-lcov
Collecting coveragepy-lcov
  Downloading coveragepy_lcov-0.1.2-py3-none-any.whl (7.7 kB)
Requirement already satisfied: coverage>=5.5 in /opt/hostedtoolcache/Python/3.10.9/x64/lib/python3.10/site-packages (from coveragepy-lcov) (7.1.0)
Requirement already satisfied: click>=7.1.2 in /opt/hostedtoolcache/Python/3.10.9/x64/lib/python3.10/site-packages (from coveragepy-lcov) (8.1.3)
Installing collected packages: coveragepy-lcov
Successfully installed coveragepy-lcov-0.1.2
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.10.9/x64/bin/coveragepy-lcov", line 5, in <module>
    from coveragepy_lcov.cli import main
  File "/opt/hostedtoolcache/Python/3.10.9/x64/lib/python3.10/site-packages/coveragepy_lcov/cli.py", line 3, in <module>
    from .converter import Converter
  File "/opt/hostedtoolcache/Python/3.10.9/x64/lib/python3.10/site-packages/coveragepy_lcov/converter.py", line 5, in <module>
    from coverage.files import FnmatchMatcher, prep_patterns
ImportError: cannot import name 'FnmatchMatcher' from 'coverage.files' (/opt/hostedtoolcache/Python/3.10.9/x64/lib/python3.10/site-packages/coverage/files.py)
Error: Process completed with exit code 1.

Please can anyone help with what is going on?

The complete main.yml file which was used on the failing run was:

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.10']
    timeout-minutes: 5

    steps:
      - uses: actions/checkout@v2

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install flake8 pytest pytest-cov coveragepy-lcov

      - name: Lint with flake8
        run: flake8 --statistics

      - name: Run unit tests with pytest and code coverage with coverage.py
        run: pytest Source/tests -v --cov

      - name: Convert Coverage Results
        run: |
          coveragepy-lcov --data_file_path .coverage --output_file_path lcov.info

      - name: Upload Coverage Results
        uses: coverallsapp/github-action@master
        with:
          github-token: ${{ secrets.github_token }}
          path-to-lcov: lcov.info

Solution

  • By fiddling with the actions commands a bit, I was able to make it work correctly.

    on: [push, pull_request]
    
    jobs:
      build:
        runs-on: ubuntu-latest
        strategy:
          matrix:
            python-version: ['3.10']
        timeout-minutes: 5
    
        steps:
          - uses: actions/checkout@v2
    
          - name: Set up Python ${{ matrix.python-version }}
            uses: actions/setup-python@v2
            with:
              python-version: ${{ matrix.python-version }}
    
          - name: Install dependencies
            run: |
              python -m pip install --upgrade pip
              pip install -r requirements.txt
              pip install flake8 pytest pytest-cov
    
          - name: Lint with flake8
            run: flake8 --statistics
    
          - name: Run unit tests with pytest and code coverage with coverage.py
            run: pytest Source/tests -v --cov=Source/ --cov-report lcov:Source/tests/lcov.info
    
          - name: Upload Coverage Results
            uses: coverallsapp/github-action@master
            with:
              github-token: ${{ secrets.github_token }}
              path-to-lcov: Source/tests/lcov.info
    

    My file directory structure was

    .github/workflows/actions.yml
    Source/
        tests/
            ...  # test files ran by pytest here
        ...  # source code here
    requirements.txt  # among others in root