# Coverage Configuration Guide

## Contents
- [pytest.ini](#pytestini)
- [pyproject.toml (empfohlen)](#pyprojecttoml)
- [.coveragerc](#coveragerc)
- [Zeilen von Coverage ausschließen](#ausschliessen)
- [CI-Integration (GitHub Actions)](#ci)

---

## pytest.ini

```ini
[pytest]
testpaths        = tests
python_files     = test_*.py *_test.py
python_classes   = Test*
python_functions = test_*

addopts =
    --cov=src
    --cov-report=term-missing:skip-covered
    --cov-report=html:htmlcov
    --cov-branch
    --cov-fail-under=90

asyncio_mode = auto
```

---

## pyproject.toml (empfohlen)

```toml
[tool.pytest.ini_options]
testpaths        = ["tests"]
python_files     = ["test_*.py", "*_test.py"]
addopts          = [
    "--cov=src",
    "--cov-report=term-missing:skip-covered",
    "--cov-report=html:htmlcov",
    "--cov-branch",
    "--cov-fail-under=90",
]
asyncio_mode     = "auto"

[tool.coverage.run]
source           = ["src"]
branch           = true
omit             = [
    "*/migrations/*",
    "*/__init__.py",
    "*/conftest.py",
    "*/settings*.py",
]

[tool.coverage.report]
precision        = 1
show_missing     = true
skip_covered     = true
exclude_lines    = [
    "pragma: no cover",
    "def __repr__",
    "if TYPE_CHECKING:",
    "raise NotImplementedError",
    "if __name__ == .__main__.:",
    "@(abc\\.)?abstractmethod",
]

[tool.coverage.html]
directory        = "htmlcov"
title            = "Coverage Report"
```

---

## .coveragerc

```ini
[run]
source  = src
branch  = True
omit    =
    */migrations/*
    */__init__.py
    */conftest.py

[report]
precision     = 1
show_missing  = True
skip_covered  = True
fail_under    = 90
exclude_lines =
    pragma: no cover
    def __repr__
    if TYPE_CHECKING:
    raise NotImplementedError
    if __name__ == .__main__.:
    @abstractmethod

[html]
directory = htmlcov
```

---

## Zeilen von Coverage ausschließen

```python
x = debug_expr()               # pragma: no cover

if TYPE_CHECKING:               # pragma: no cover
    from mymodule import Type

def _never_called(self):
    raise NotImplementedError  # pragma: no cover
```

**Regel:** Nur echten Nicht-Produktions-Code ausschließen.
Nie schlechte Tests mit `pragma: no cover` verstecken.

---

## CI-Integration (GitHub Actions)

```yaml
name: Tests & Coverage
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.9", "3.10", "3.11", "3.12"]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install dependencies
        run: |
          pip install -e ".[dev]"
          pip install pytest pytest-cov pytest-mock pytest-asyncio
      - name: Run tests with coverage
        run: |
          pytest --cov=src --cov-branch --cov-fail-under=90 \
                 --cov-report=xml --cov-report=term-missing
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          files: coverage.xml
          fail_ci_if_error: true
```
