Comprehensive guide for running tests in the MCP Server LangGraph project. This document ensures local testing matches CI/CD behavior exactly.
- Quick Start
- Test Types
- Running Tests Locally
- Matching CI/CD Behavior
- Coverage Reports
- Development Workflow
- Continuous Integration
- Troubleshooting
# Install dependencies
make install-dev
# Run all tests with coverage (matches CI)
make test-unit
# Fast iteration without coverage
make test-unit-fast
# Integration tests (Docker-based, same as CI)
make test-integration- Marker:
@pytest.mark.unit - Purpose: Test individual components in isolation
- Dependencies: None (uses mocks)
- Speed: Fast (<1 second per test)
- Command:
make test-unit
- Marker:
@pytest.mark.integration - Purpose: Test component interactions
- Dependencies: Docker services (OpenFGA, Keycloak, Redis, PostgreSQL)
- Speed: Medium (1-5 seconds per test)
- Command:
make test-integration
- Marker:
@pytest.mark.e2e - Purpose: Test complete user workflows
- Dependencies: Full system running
- Speed: Slow (5+ seconds per test)
- Command:
pytest -m e2e
- Marker:
@pytest.mark.property - Purpose: Test invariants with generated inputs (Hypothesis)
- Dependencies: None
- Speed: Medium (100+ test cases generated)
- Command:
make test-property
- Marker:
@pytest.mark.contract - Purpose: Validate API contracts (OpenAPI, MCP protocol)
- Dependencies: Schema files
- Speed: Fast
- Command:
make test-contract
- Marker:
@pytest.mark.regression - Purpose: Detect performance degradations
- Dependencies: Baseline metrics
- Speed: Medium
- Command:
make test-regression
# Run all tests with coverage report
make test
# This runs: pytest (uses pyproject.toml defaults)
# - Coverage enabled by default
# - Matches CI/CD behavior
# - Output: Terminal coverage report# With coverage (matches CI)
make test-unit
# Without coverage (fast iteration)
make test-unit-fast
# Exactly as CI runs them
make test-ci# Docker-based (matches CI exactly)
make test-integration
# Local services (faster, but differs from CI)
make test-integration-local
# Rebuild containers and test
make test-integration-build
# Keep containers for debugging
make test-integration-debug
# Cleanup test containers
make test-integration-cleanup# Property-based tests
make test-property
# Contract tests
make test-contract
# Performance regression tests
make test-regression
# All quality tests
make test-all-quality# GDPR, SOC2, HIPAA, SLA tests
make test-compliance
# Individual compliance tests
pytest -m gdpr
pytest -m soc2
pytest -m slaTo run tests exactly as they run in CI/CD:
# Unit tests (CI/CD Pipeline workflow)
make test-ci
# Integration tests (same Docker environment as CI)
make test-integration
# Quality tests (weekly schedule)
make test-property
make test-contract
make test-regression| ❌ Avoid | ✅ Use Instead | Reason |
|---|---|---|
pytest (without markers) |
make test-unit |
Runs all tests including slow ones |
make test-integration-local |
make test-integration |
CI uses Docker, not local services |
pytest --no-cov (in CI testing) |
make test-ci |
CI always runs with coverage |
| Custom pytest flags | Use Makefile targets | Ensures consistency |
Tool Versions (as of 2025-10-15):
# Formatters (flexible - use latest)
black >= 24.1.1
isort >= 7.0.0
# Static Analysis (pinned - exact versions)
flake8 == 7.3.0
mypy == 1.18.2
# Test Framework (flexible minimum)
pytest >= 8.2.0
pytest-asyncio == 0.26.0
pytest-cov == 4.1.0Updating Versions:
- Local changes: Update
pyproject.tomldev dependencies - CI changes: Update
requirements-test.txt - Both should stay in sync!
make test-unit
# Output:
# Name Stmts Miss Cover Missing
# --------------------------------------------------------------
# src/mcp_server_langgraph/... 1234 123 90% 45-67, 89-92make test-coverage
open htmlcov/index.html # macOS
xdg-open htmlcov/index.html # Linuxpytest --cov=src/mcp_server_langgraph --cov-report=xml
# Generates: coverage.xmlLocation: pyproject.toml
[tool.coverage.run]
source = ["src/mcp_server_langgraph"]
omit = [
"*/venv/*",
"*/tests/*",
"*/examples/*",
...
]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:",
...
]During active development, skip coverage for speed:
# Fast unit tests
make test-unit-fast
# Watch mode (re-runs on file changes)
make test-watch
# Specific test file
pytest tests/test_session.py --no-cov
# Specific test function
pytest tests/test_session.py::TestInMemorySessionStore::test_create_session --no-covBefore committing code:
# 1. Run fast tests
make test-unit-fast
# 2. Run formatters
make format
# 3. Run linters
make lint
# 4. Full test with coverage
make test-unit
# 5. Integration tests (if changed integration code)
make test-integrationBefore pushing to remote:
# 1. Exactly match CI
make test-ci
# 2. Integration tests
make test-integration
# 3. Validate deployments
make validate-all1. CI/CD Pipeline (.github/workflows/ci.yaml)
- Trigger: Push to
main,develop, PRs - Tests: Unit tests, integration tests
- Coverage: Yes (uploaded to Codecov)
- Command:
pytest -m unit --cov=src/mcp_server_langgraph --cov-report=xml
2. Quality Tests (.github/workflows/quality-tests.yaml)
- Trigger: Push to
main, PRs, weekly schedule - Tests: Property, contract, regression tests
- Coverage: No (performance-focused)
- Commands:
pytest -m property -vpytest -m contract -vpytest -m regression -v
3. Mutation Testing (.github/workflows/quality-tests.yaml)
- Trigger: Weekly schedule only (slow)
- Tests: Mutation tests with mutmut
- Purpose: Test effectiveness validation
| CI Workflow | Local Command | Purpose |
|---|---|---|
| CI/CD Pipeline → Test | make test-ci |
Unit tests with coverage |
| CI/CD Pipeline → Lint | make lint && make format |
Code quality checks |
| Quality Tests → Property | make test-property |
Property-based tests |
| Quality Tests → Contract | make test-contract |
API contract validation |
| Quality Tests → Regression | make test-regression |
Performance regression |
| Quality Tests → Mutation | make test-mutation |
Test effectiveness |
Common Causes:
-
Version mismatch
# Check versions pip list | grep -E "pytest|black|isort|flake8|mypy" # Reinstall exact CI versions pip install -r requirements-test.txt --force-reinstall
-
Coverage differences
# Use exact CI command make test-ci -
Environment variables
# Check .env file # CI uses GitHub Secrets
-
Docker services
# Use Docker-based integration tests make test-integration # Not make test-integration-local
Issue: Coverage includes files from venv/ or tests/
Solution: Already fixed in pyproject.toml → Coverage scope is src/mcp_server_langgraph
# Verify coverage configuration
grep -A 10 "\[tool.coverage.run\]" pyproject.tomlFast Options:
# Skip coverage
pytest --no-cov
# Run only fast tests
pytest -m "not slow"
# Parallel execution
pytest -n auto
# Specific marker
pytest -m unit --no-covCommon Issues:
-
Services not running
make setup-infra docker compose ps
-
Port conflicts
# Check ports: 8080, 5432, 8081, 16686, 9090, 3000, 6379 lsof -i :8080 -
Docker version
docker --version # Should be 20.10+ docker compose version # Should be 2.0+
Issue: ModuleNotFoundError for mcp_server_langgraph
Solution:
# Install package in editable mode
pip install -e .
# Or use uv
uv pip install -e .Issue: mypy reports errors locally but not in CI (or vice versa)
Solution:
# Use exact CI mypy version
pip install mypy==1.18.2
# Check configuration
mypy src/ --ignore-missing-imports- Use
make test-unitfor regular testing (matches CI) - Use
make test-unit-fastfor quick iteration - Run
make test-cibefore pushing - Use Docker-based integration tests (
make test-integration) - Keep
requirements-test.txtandpyproject.tomlin sync - Add markers to new tests (
@pytest.mark.unit, etc.)
- Run
pytestwithout markers (runs everything) - Use
make test-integration-localto validate CI behavior - Modify pytest flags in CI without updating Makefile
- Skip coverage checks before committing
- Run integration tests without Docker in CI validation
# Most Common Commands
make test-unit # Unit tests with coverage
make test-unit-fast # Fast unit tests (no coverage)
make test-ci # Exact CI match
make test-integration # Integration tests (Docker)
make test-coverage # Full coverage report (HTML)
make format # Format code (black + isort)
make lint # Run linters
make test-all-quality # All quality tests
# Test Selection
pytest -m unit # Only unit tests
pytest -m integration # Only integration tests
pytest -m "unit and not slow" # Fast unit tests
pytest -k "test_session" # Name pattern matching
pytest tests/test_session.py # Specific file
# Coverage Options
pytest --cov=src/mcp_server_langgraph # Default coverage
pytest --no-cov # Skip coverage
pytest --cov-report=html # HTML report
pytest --cov-report=term-missing # Terminal with missing lines- pytest Documentation
- Hypothesis Documentation
- Coverage.py Documentation
- Project README
- Contributing Guide
Last Updated: 2025-10-15 Python Version: 3.12 pytest Version: 8.2.0+ Coverage Target: 70%+ (Current: 86%)