test: set up coverage infrastructure in CI

- Add pytest-cov to dev dependencies
- Add .coveragerc with branch coverage, 60% floor (current baseline),
  and source/omit configuration
- Add coverage CI job (ubuntu/py3.13) that runs pytest with --cov,
  enforces the floor, and uploads coverage.xml as an artifact
- Wire coverage into the required-checks-passed gate

Closes #2080
This commit is contained in:
Kevin Turcios 2026-04-23 02:30:46 -05:00
parent 67cf123929
commit 2c79e50d68
4 changed files with 85 additions and 0 deletions

17
.coveragerc Normal file
View file

@ -0,0 +1,17 @@
[run]
branch = true
source = codeflash
omit =
codeflash/version.py
[report]
sort = cover
show_missing = true
fail_under = 60
exclude_lines =
pragma: no cover
if TYPE_CHECKING:
if __name__ == .__main__.:
[html]
directory = htmlcov

View file

@ -151,6 +151,44 @@ jobs:
- name: Unit tests
run: uv run pytest tests/
# ---------------------------------------------------------------------------
# Coverage — single run on ubuntu/py3.13 to enforce the coverage floor.
# ---------------------------------------------------------------------------
coverage:
needs: determine-changes
if: needs.determine-changes.outputs.unit_tests == 'true'
runs-on: ubuntu-latest
env:
PYTHONIOENCODING: utf-8
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install uv
uses: astral-sh/setup-uv@v8.0.0
with:
python-version: "3.13"
enable-cache: true
- name: Install dependencies
run: uv sync
- name: Run tests with coverage
run: uv run pytest tests/ --cov=codeflash --cov-report=xml:coverage.xml --cov-report=term-missing --cov-config=.coveragerc
- name: Check coverage floor
run: uv run coverage report --fail-under=60
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage.xml
retention-days: 30
# ---------------------------------------------------------------------------
# Mypy type checking
# ---------------------------------------------------------------------------
@ -507,6 +545,7 @@ jobs:
if: always()
needs:
- unit-tests
- coverage
- type-check
- prek
- e2e-python

View file

@ -89,6 +89,7 @@ dev = [
"prek>=0.2.25",
"ty>=0.0.14",
"uv>=0.9.29",
"pytest-cov>=7.1.0",
]
tests = [
"black>=25.9.0",

28
uv.lock
View file

@ -507,6 +507,7 @@ dev = [
{ name = "pandas-stubs", version = "2.2.2.240807", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "pandas-stubs", version = "2.2.2.240909", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
{ name = "prek" },
{ name = "pytest-cov" },
{ name = "ruff" },
{ name = "ty" },
{ name = "types-cffi", version = "1.17.0.20250915", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
@ -608,6 +609,7 @@ dev = [
{ name = "mypy", specifier = ">=1.13" },
{ name = "pandas-stubs", specifier = ">=2.2.2.240807,<2.2.3.241009" },
{ name = "prek", specifier = ">=0.2.25" },
{ name = "pytest-cov", specifier = ">=7.1.0" },
{ name = "ruff", specifier = ">=0.7.0" },
{ name = "ty", specifier = ">=0.0.14" },
{ name = "types-cffi", specifier = ">=1.16.0.20240331" },
@ -776,6 +778,11 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/16/114df1c291c22cac3b0c127a73e0af5c12ed7bbb6558d310429a0ae24023/coverage-7.10.7-py3-none-any.whl", hash = "sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260", size = 209952, upload-time = "2025-09-21T20:03:53.918Z" },
]
[package.optional-dependencies]
toml = [
{ name = "tomli", marker = "python_full_version < '3.10'" },
]
[[package]]
name = "coverage"
version = "7.13.5"
@ -904,6 +911,11 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/9e/ee/a4cf96b8ce1e566ed238f0659ac2d3f007ed1d14b181bcb684e19561a69a/coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61", size = 211346, upload-time = "2026-03-17T10:33:15.691Z" },
]
[package.optional-dependencies]
toml = [
{ name = "tomli", marker = "python_full_version >= '3.10' and python_full_version <= '3.11'" },
]
[[package]]
name = "crosshair-tool"
version = "0.0.102"
@ -4515,6 +4527,22 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" },
]
[[package]]
name = "pytest-cov"
version = "7.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" },
{ name = "coverage", version = "7.13.5", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" },
{ name = "pluggy" },
{ name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" },
]
[[package]]
name = "pytest-memray"
version = "1.8.0"