forked from apache/cassandra-python-driver
-
Notifications
You must be signed in to change notification settings - Fork 57
Add code coverage measurement for unit and integration tests #967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
roydahan
wants to merge
2
commits into
scylladb:master
Choose a base branch
from
roydahan:claude/code-coverage-tool-plan-474b86
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| name: Code coverage | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - master | ||
| - 'branch-**' | ||
| paths-ignore: | ||
| - docs/* | ||
| - examples/* | ||
| - .gitignore | ||
| - '*.rst' | ||
| - '*.ini' | ||
| - LICENSE | ||
| - .github/dependabot.yml | ||
| - .github/pull_request_template.md | ||
| - "*.md" | ||
| - .github/workflows/docs-* | ||
| pull_request: | ||
| paths-ignore: | ||
| - docs/* | ||
| - examples/* | ||
| - .gitignore | ||
| - '*.rst' | ||
| - '*.ini' | ||
| - LICENSE | ||
| - .github/dependabot.yml | ||
| - .github/pull_request_template.md | ||
| - "*.md" | ||
| - .github/workflows/docs-* | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| coverage: | ||
| name: Measure code coverage | ||
| if: "!contains(github.event.pull_request.labels.*.name, 'disable-coverage-tests')" | ||
| runs-on: ubuntu-24.04 | ||
| env: | ||
| SCYLLA_VERSION: release:2026.1 | ||
| PROTOCOL_VERSION: 4 | ||
| # Set once at job level so every step (including "Build driver" and the | ||
| # summary step, both of which invoke `uv run`) sees the same value. | ||
| # uv's cache-keys include this var, so a value that flips between steps | ||
| # makes each `uv run` re-detect a "changed" build config and rebuild the | ||
| # Cython extensions from scratch -- about two minutes wasted per flip. | ||
| CASS_DRIVER_NO_CYTHON: "1" | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
|
|
||
| - name: Set up JDK 8 | ||
| uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 | ||
| with: | ||
| java-version: 8 | ||
| distribution: 'adopt' | ||
|
|
||
| - name: Install libev | ||
| run: sudo apt-get install libev4 libev-dev | ||
|
|
||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 | ||
| with: | ||
| python-version: "3.13" | ||
|
|
||
| - name: Build driver | ||
| run: uv sync | ||
|
|
||
| - name: Cache Scylla download | ||
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 | ||
| with: | ||
| path: ~/.ccm/repository | ||
| key: scylla-${{ env.SCYLLA_VERSION }}-${{ runner.os }} | ||
|
|
||
| - name: Download Scylla | ||
| run: | | ||
| uv run ccm create scylla-driver-temp -n 1 --scylla --version ${SCYLLA_VERSION} | ||
| uv run ccm remove | ||
|
|
||
| - name: Run tests with coverage | ||
| run: bash scripts/coverage.sh | ||
|
|
||
| - name: Publish coverage summary | ||
| if: always() | ||
| run: | | ||
| { | ||
| echo '## Coverage report' | ||
| echo '```' | ||
| uv run coverage report -m | ||
| echo '```' | ||
| } >> "$GITHUB_STEP_SUMMARY" | ||
|
|
||
| - name: Upload coverage report | ||
| if: always() | ||
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | ||
| with: | ||
| name: coverage-report | ||
| path: | | ||
| htmlcov/ | ||
| coverage.xml | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| #!/usr/bin/env bash | ||
| # Runs the unit suite (all event-loop reactors) and, if SCYLLA_VERSION or | ||
| # CASSANDRA_VERSION is set, the integration suite, all under coverage.py, then | ||
| # combines and reports. | ||
| # | ||
| # CASS_DRIVER_NO_CYTHON=1 forces cluster.py/connection.py/protocol.py/etc. to | ||
| # build as plain Python instead of Cython extensions, since coverage.py can't | ||
| # trace into compiled extensions. Cython-only modules with no .py fallback | ||
| # (obj_parser, numpy_parser, row_parser, ...) are not built at all in this mode | ||
| # and are therefore not measured by this script. | ||
| # | ||
| # Deliberately not `set -e`: a failing test must not skip report generation | ||
| # below, or a broken test leaves no coverage output at all to diagnose it | ||
| # with. Each test invocation instead records its own failure into $status, | ||
| # and the script exits with that status only after combine/report/html/xml | ||
| # have run. | ||
| set -uo pipefail | ||
| cd "$(dirname "$0")/.." || exit 1 | ||
|
|
||
| rm -f .coverage .coverage.* || exit 1 | ||
| export CASS_DRIVER_NO_CYTHON=1 | ||
|
|
||
| # A previous plain `uv sync`/`uv run` may have left Cython-compiled .so/.pyd | ||
| # files in place from a normal (Cython-enabled) build. Python's import system | ||
| # prefers those over the .py source, so they must be removed -- otherwise | ||
| # CASS_DRIVER_NO_CYTHON=1 silently has no effect and coverage reports 0% for | ||
| # every affected module (and, for the Cython-only modules with no .py | ||
| # fallback like row_parser, HAVE_CYTHON would stay True off a stale .so, | ||
| # defeating CASS_DRIVER_NO_CYTHON entirely). Only extensions matching the | ||
| # *current* interpreter's own EXTENSION_SUFFIXES are removed -- the same | ||
| # mechanism tests/conftest.py already uses to detect staleness -- so this | ||
| # doesn't force a rebuild for other Python versions/venvs sharing this | ||
| # checkout. murmur3/libev are excluded by name since they're unaffected by | ||
| # CASS_DRIVER_NO_CYTHON. `--reinstall-package` then rebuilds from scratch, | ||
| # producing only the extensions CASS_DRIVER_NO_CYTHON=1 actually allows. If | ||
| # any of this setup fails, there's no point running any tests, so bail out | ||
| # immediately -- failure tolerance below is scoped to test/report commands | ||
| # only. | ||
| uv run python -c " | ||
| import importlib.machinery, pathlib | ||
| exclude = {'cmurmur3', 'libevwrapper'} | ||
| for path in pathlib.Path('cassandra').rglob('*'): | ||
| for suffix in importlib.machinery.EXTENSION_SUFFIXES: | ||
| if path.name.endswith(suffix): | ||
| if path.name[:-len(suffix)] not in exclude: | ||
| path.unlink() | ||
| break | ||
| " || exit 1 | ||
| uv sync --reinstall-package scylla-driver || exit 1 | ||
|
|
||
| status=0 | ||
|
|
||
| # Unlike the gevent/eventlet/asyncio reactor tests below, tests/unit/io/ | ||
| # test_asyncorereactor.py is deliberately NOT in the --ignore list: it needs | ||
| # no separate EVENT_LOOP_MANAGER run, since it self-skips via | ||
| # ASYNCCORE_AVAILABLE on Python 3.12+ (where the stdlib `asyncore` module was | ||
| # removed) and otherwise runs normally here, gaining coverage on 3.9-3.11. | ||
| uv run coverage run -m pytest tests/unit -v \ | ||
| --ignore=tests/unit/column_encryption \ | ||
| --ignore=tests/unit/io/test_geventreactor.py \ | ||
| --ignore=tests/unit/io/test_eventletreactor.py \ | ||
| --ignore=tests/unit/io/test_asyncioreactor.py \ | ||
| || status=1 | ||
|
|
||
| # gevent/eventlet monkey-patch threading/sockets, which can confuse | ||
| # coverage.py's default sys.settrace-based collector; --concurrency tells it | ||
| # about the greenlet scheduler explicitly. asyncio and the default (thread) | ||
| # runs need no such hint. | ||
| EVENT_LOOP_MANAGER=gevent uv run coverage run --concurrency=gevent,thread -m pytest tests/unit/io/test_geventreactor.py -v || status=1 | ||
| EVENT_LOOP_MANAGER=asyncio uv run coverage run -m pytest tests/unit/io/test_asyncioreactor.py -v || status=1 | ||
| EVENT_LOOP_MANAGER=eventlet uv run coverage run --concurrency=eventlet,thread -m pytest tests/unit/io/test_eventletreactor.py -v || status=1 | ||
|
|
||
| if [[ -n "${SCYLLA_VERSION:-}" || -n "${CASSANDRA_VERSION:-}" ]]; then | ||
| uv run coverage run -m pytest tests/integration/standard tests/integration/cqlengine/ -v || status=1 | ||
| else | ||
| echo "SCYLLA_VERSION/CASSANDRA_VERSION not set -- skipping integration coverage." | ||
| fi | ||
|
|
||
| uv run coverage combine || status=1 | ||
| uv run coverage report -m || status=1 | ||
| uv run coverage html || status=1 | ||
| uv run coverage xml || status=1 | ||
|
|
||
| exit "$status" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.