# Testing Coverage Guide

## Understanding the Coverage Issue

### The Problem

When running route tests with coverage requirements:
```bash
pytest -m routes --cov=app --cov-fail-under=50
```

You may see:
```
FAIL Required test coverage of 50% not reached. Total coverage: 27.81%
```

### Why This Happens

The issue occurs because:

1. **Route tests only exercise route handlers** - They test the endpoints in `app/routes/`
2. **Coverage measures the entire `app` module** - Including models, utils, config, etc.
3. **Most code isn't executed by routes alone** - Models, utilities, and business logic require comprehensive testing across all test types

This is **conceptually correct behavior**. Route tests shouldn't execute 50% of your entire codebase - they should test routes. Other code is tested by model tests, integration tests, etc.

## Solutions

### Option 1: Run Tests Without Marker-Specific Coverage (Recommended)

**For development and debugging specific test categories:**
```bash
# Run route tests without coverage requirements
make test-routes

# Or directly:
pytest -m routes -v
```

**For comprehensive coverage analysis:**
```bash
# Run ALL tests with coverage requirement
make test-coverage

# Or directly:
pytest --cov=app --cov-report=html --cov-report=term-missing --cov-fail-under=50
```

### Option 2: Measure Coverage Only for Routes

If you specifically want to measure route coverage:
```bash
# Measure coverage only for the routes module
pytest -m routes --cov=app/routes --cov-report=term-missing
```

This will show you what percentage of your routes are tested, not the entire app.

### Option 3: Run Coverage on All Tests Together

The standard approach in most projects:
```bash
# Run all tests together with coverage
pytest --cov=app --cov-report=html --cov-report=term-missing --cov-fail-under=50
```

This gives you the true coverage across your entire test suite.

## Test Organization Strategy

### Test Markers

The project uses pytest markers to organize tests:

- `@pytest.mark.smoke` - Critical functionality (health checks, basic routes)
- `@pytest.mark.unit` - Unit tests (isolated, fast)
- `@pytest.mark.integration` - Integration tests (multiple components)
- `@pytest.mark.routes` - Route/endpoint tests
- `@pytest.mark.api` - API endpoint tests
- `@pytest.mark.models` - Model tests
- `@pytest.mark.database` - Database tests
- `@pytest.mark.security` - Security tests

### Running Different Test Suites

```bash
# Quick smoke test (fastest, for CI)
make test-smoke

# Unit tests only
make test-unit

# Integration tests
make test-integration

# Route tests (no coverage requirement)
make test-routes

# Model tests
make test-models

# API tests
make test-api

# Full test suite with 50% coverage requirement
make test-coverage

# Generate coverage report without failing on threshold
make test-coverage-report
```

## Coverage Targets by Test Type

Different test types have different coverage expectations:

| Test Type | Expected Coverage | Scope |
|-----------|------------------|-------|
| Smoke tests | Low (~10-20%) | Critical paths only |
| Route tests | Low (~20-30%) | Routes + directly called utilities |
| Model tests | Medium (~30-40%) | Models + database operations |
| Unit tests | Medium (~40-60%) | Specific modules being tested |
| Integration tests | High (~60-80%) | Multiple components together |
| **Full suite** | **High (50%+)** | **Entire codebase** |

## Best Practices

### 1. Don't Enforce Coverage on Marker-Specific Tests

❌ **Wrong:**
```bash
pytest -m routes --cov=app --cov-fail-under=50
```

✅ **Correct:**
```bash
# For debugging/development
pytest -m routes -v

# For coverage analysis
pytest --cov=app --cov-fail-under=50
```

### 2. Use Coverage to Find Gaps, Not as a Goal

Coverage percentage is a tool to find untested code, not a target to hit. Focus on:
- Testing critical functionality
- Testing edge cases
- Testing error conditions
- Testing user workflows

### 3. Combine Test Types for Complete Coverage

```bash
# This is how to get meaningful coverage
pytest tests/ --cov=app --cov-report=html --cov-fail-under=50
```

Individual test types complement each other:
- **Route tests**: Ensure endpoints work
- **Model tests**: Ensure data integrity
- **Integration tests**: Ensure components work together
- **Unit tests**: Ensure individual functions work

### 4. Review Coverage Reports

After running tests with coverage:
```bash
# Generate HTML report
pytest --cov=app --cov-report=html

# Open the report
# The report is in htmlcov/index.html
```

Look for:
- Untested critical paths
- Error handling code
- Edge cases
- Business logic

## CI/CD Coverage Strategy

### Development (develop branch)
- Runs smoke tests only (fast feedback)
- No coverage requirements
- Focus on catching obvious breaks

### Pull Requests
- Runs full test suite
- No strict coverage requirement yet
- Migration validation for model changes

### Release (main/master branch)
- Runs full test suite
- Enforces 50% coverage requirement
- Security audit
- Integration tests

## Current Test Coverage

To see current coverage:
```bash
# Run tests with coverage
make test-coverage-report

# View HTML report
open htmlcov/index.html  # macOS
xdg-open htmlcov/index.html  # Linux
start htmlcov/index.html  # Windows
```

## Adding More Route Tests

If you want to improve route test coverage, add tests for:

### Missing Route Tests
- Task routes (`/tasks/*`)
- Comment routes (`/comments/*`)
- More comprehensive API tests
- Form submission tests
- File upload tests
- Pagination tests

### Example: Adding Task Route Tests

```python
# tests/test_routes.py

@pytest.mark.integration
@pytest.mark.routes
def test_tasks_list_page(authenticated_client):
    """Test tasks list page."""
    response = authenticated_client.get('/tasks')
    assert response.status_code == 200

@pytest.mark.integration
@pytest.mark.routes
def test_task_create_page(authenticated_client, project):
    """Test task creation page."""
    response = authenticated_client.get(f'/tasks/new?project_id={project.id}')
    assert response.status_code == 200

@pytest.mark.integration
@pytest.mark.routes
@pytest.mark.api
def test_create_task_api(authenticated_client, project, user, app):
    """Test creating a task via API."""
    with app.app_context():
        response = authenticated_client.post('/api/tasks', json={
            'name': 'Test Task',
            'project_id': project.id,
            'description': 'Test task description',
            'priority': 'medium'
        })
        assert response.status_code in [200, 201]
```

## Troubleshooting

### "pytest: error: unrecognized arguments: --cov=app"

This means `pytest-cov` is not installed:
```bash
pip install -r requirements-test.txt
```

### Coverage too low even with all tests

This is normal if you have:
- Large utility modules
- Configuration code
- Error handling code
- Admin-only features
- Legacy code

Focus on:
1. Test critical user paths
2. Test error conditions
3. Test business logic
4. Don't worry about 100% coverage

### Tests pass individually but fail in suite

This usually indicates:
- Test pollution (tests affecting each other)
- Shared state issues
- Database not being cleaned between tests

Fix by using proper fixtures and isolation.

## Summary

✅ **Do:**
- Run full test suite for coverage analysis
- Use markers to organize and run specific test types
- Focus on testing critical functionality
- Use coverage reports to find gaps

❌ **Don't:**
- Enforce coverage thresholds on marker-specific tests
- Chase 100% coverage
- Write tests just to increase coverage percentage
- Mix coverage analysis with debugging/development testing

## Quick Reference

```bash
# Development workflow
make test-routes          # Debug route tests
make test-models          # Debug model tests
make test-unit           # Debug unit tests

# CI/CD workflow
make test-smoke          # Quick validation
make test-coverage       # Full coverage with 50% threshold

# Coverage analysis
make test-coverage-report  # Generate report without failing
open htmlcov/index.html    # Review coverage
```

