til/pytest/pytest-code-coverage.md
# Code coverage using pytest and codecov.ioI got my [asgi-csrf](https://github.com/simonw/asgi-csrf) Python package up to 100% code coverage. Here's [the pull request](https://github.com/simonw/asgi-csrf/issues/13).I started by installing and using the [pytest-cov](https://pypi.org/project/pytest-cov/) pytest plugin.```pip install pytest-covpytest --cov=asgi_csrf```This shows the current code coverage percentage for the `asgi_csrf` module in the terminal output:```collected 18 itemstest_asgi_csrf.py .................. [100%]---------- coverage: platform darwin, python 3.7.3-final-0 -----------Name Stmts Miss Cover----------------------------------asgi_csrf.py 169 13 92%========= 18 passed in 0.37s =========```To generate an HTML report showing which lines are not covered by tests:```pytest --cov=asgi_csrf --cov-report=htmlopen htmlcov/index.html```Here's a hosted copy of that report: https://asgi-csrf-htmlcov-ewca4t9se.vercel.app/asgi_csrf_py.html## Failing the tests if coverage is below a certain thresholdThe `--cov-fail-under=100` option does this:```pytest --cov-fail-under=100 --cov asgi_csrf======= test session starts =======platform darwin -- Python 3.7.3, pytest-6.0.1, py-1.9.0, pluggy-0.13.1rootdir: /Users/simon/Dropbox/Development/asgi-csrfplugins: cov-2.10.1, asyncio-0.14.0collected 18 itemstest_asgi_csrf.py .................. [100%]---------- coverage: platform darwin, python 3.7.3-final-0 -----------Name Stmts Miss Cover----------------------------------asgi_csrf.py 169 13 92%FAIL Required test coverage of 100% not reached. Total coverage: 92.31%```I added this to my [GitHub test action](https://github.com/simonw/asgi-csrf/blob/83d2b4f6bb034b746fd3f20f57ebdbaeae007a73/.github/workflows/test.yml#L27-L29):```yaml- name: Run testsrun: |pytest --cov-fail-under=100 --cov asgi_csrf```## Pushing results to codecov.iohttps://codecov.io/ offers free coverage reporting for open source projects. I authorized it against my GitHub account, then enabled it for the `asgi-csrf` project by navigating to https://codecov.io/gh/simonw/asgi-csrf (hacking the URL saves you from having to paginate through all of your repos looking for the right one).codecov.io gives you a token - set that as a GitHub repository secret as `CODECOV_TOKEN` - then add the following to the test action configuration:```yaml- name: Upload coverage to codecov.iorun: bash <(curl -s https://codecov.io/bash)if: always()env:CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}```This will upload your coverage report (no matter if the previous test step failed or succeeded). codecove.io then reports back to pull requests and maintains a dashboard for your project.codecov.io doesn't detect if you use a `main` or `master` branch so I had to switch the default branch in the settings at https://codecov.io/gh/simonw/asgi-csrf/settingsI also added their badge to my project README, using the following Markdown:```[](https://codecov.io/gh/simonw/asgi-csrf)```