diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 00000000..00c82925 --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,38 @@ +coverage: + status: + project: + default: + target: auto # do not drop below the current level... + threshold: 1% # ...by more than 1% + patch: + default: + target: 80% # new/changed code in the PR diff must be >= 80% covered + +flags: + unit: + paths: + - ydb/ + carryforward: true + integration: + paths: + - ydb/ + carryforward: true + +comment: + layout: "reach, diff, flags, files" + require_changes: false + +# Auto-generated protobuf stubs and tests must not affect the metric. +# Already excluded from coverage.xml via [tool.coverage.run] omit, listed here for safety. +ignore: + - "ydb/_grpc/v3" + - "ydb/_grpc/v4" + - "ydb/_grpc/v5" + - "ydb/_grpc/v6" + - "ydb/dbapi" # legacy + - "ydb/sqlalchemy" # legacy + - "**/*_test.py" + - "tests" + - "examples" + - "docs" + - "benchmarks" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 8e271a1e..6441d710 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -61,3 +61,54 @@ jobs: - name: Run unit tests run: tox -e py -- ydb + + coverage: + runs-on: ubuntu-latest + + concurrency: + group: coverage-${{ github.ref }} + cancel-in-progress: true + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install tox + run: | + python -m pip install --upgrade pip + pip install tox==4.2.6 + + # sysmon (PEP 669) keeps tracer overhead low so timing-sensitive chaos + # tests (which kill/restart YDB) still pass under coverage. Requires py3.12+. + - name: Unit tests with coverage + env: + COVERAGE_CORE: sysmon + run: tox -e cov -- ydb + + - name: Upload unit coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage.xml + flags: unit + name: unit + # The gate is enforced via Codecov status checks (branch protection), + # so don't fail CI on transient upload errors. + fail_ci_if_error: false + + - name: Integration tests with coverage + env: + COVERAGE_CORE: sysmon + run: tox -e cov -- tests + + - name: Upload integration coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage.xml + flags: integration + name: integration + fail_ci_if_error: false diff --git a/.gitignore b/.gitignore index 36b3d2e2..53ad54d2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,9 @@ ydb.egg-info/ /ydb_data /tmp .coverage +.coverage.* /cov_html +/coverage.xml /build docs/_build .DS_Store diff --git a/README.md b/README.md index 7842bd1d..eeda8db3 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ YDB Python SDK [![API Reference](https://img.shields.io/badge/API-Reference-lightgreen.svg)](https://ydb-platform.github.io/ydb-python-sdk) [![Functional tests](https://github.com/ydb-platform/ydb-python-sdk/actions/workflows/tests.yaml/badge.svg)](https://github.com/ydb-platform/ydb-python-sdk/actions/workflows/tests.yaml) [![Style checks](https://github.com/ydb-platform/ydb-python-sdk/actions/workflows/style.yaml/badge.svg)](https://github.com/ydb-platform/ydb-python-sdk/actions/workflows/style.yaml) +[![codecov](https://codecov.io/gh/ydb-platform/ydb-python-sdk/graph/badge.svg)](https://codecov.io/gh/ydb-platform/ydb-python-sdk) Officially supported Python client for YDB. diff --git a/pyproject.toml b/pyproject.toml index 0b08f0b2..eaca5950 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,3 +49,29 @@ ignore_missing_imports = true [[tool.mypy.overrides]] module = ["ydb.types", "ydb.table"] disable_error_code = ["attr-defined"] + +[tool.coverage.run] +branch = true +source = ["ydb"] +# Auto-generated protobuf stubs and test files must not skew the metric. +omit = [ + "ydb/_grpc/v3/*", + "ydb/_grpc/v4/*", + "ydb/_grpc/v5/*", + "ydb/_grpc/v6/*", + "*_test.py", + # Legacy, no longer actively developed. + "ydb/dbapi/*", + "ydb/sqlalchemy/*", +] + +[tool.coverage.report] +show_missing = true +exclude_also = [ + "if TYPE_CHECKING:", + "raise NotImplementedError", + "@(abc\\.)?abstractmethod", +] + +[tool.coverage.html] +directory = "cov_html" diff --git a/test-requirements.txt b/test-requirements.txt index 95c09dc2..180769bf 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -44,6 +44,6 @@ pylint-protobuf cython freezegun>=1.3.0 opentelemetry-sdk>=1.0.0 -# pytest-cov +pytest-cov>=4.0.0 yandexcloud -e . diff --git a/tox.ini b/tox.ini index 986b0d5e..064ff46e 100644 --- a/tox.ini +++ b/tox.ini @@ -33,6 +33,14 @@ deps = -r{toxinidir}/test-requirements.txt protobuf<6.0.0 +[testenv:cov] +passenv = COVERAGE_CORE +commands = + pytest -v --cov --cov-report=term-missing --cov-report=html --cov-report=xml {posargs} +deps = + -r{toxinidir}/test-requirements.txt + protobuf<7.0.0 + [testenv:py-proto4] commands = pytest -v {posargs}