feat: tiered test infrastructure with Makefile + smart selector + OpenCode commands
Root Makefile with timeout-protected test targets: - Tier 1 (<30s): make test, make test-unit, make test-frontend - Tier 2 (smart): make test-related F=file.py (via @RELATION BINDS_TO) - Tier 3 (<5min): make test-integration (Docker, --run-integration) - Coverage: make coverage (backend + frontend) - Lint: make lint (ruff + eslint) Smart test selector (scripts/find-related-tests.py): - Extracts module names from #region anchors, class/function defs - Searches 400 BINDS_TO entries across all test files - Confidence scoring: exact > case-insensitive > substring > heuristic - Fallback: filename-based fuzzy matching OpenCode commands: - /test.all — full suite + coverage - /test.unit — fast unit tests (<30s) - /test.related — smart selection by file - /test.coverage — coverage reports with thresholds Speckit workflow updated: - speckit.test.md: raw pytest → make targets with timeout safety - speckit.plan.md: quickstart uses make targets - speckit.tasks.md: verification uses make targets - speckit.implement.md: default stack uses make targets Frontend: added 'coverage' script to package.json
This commit is contained in:
87
Makefile
Normal file
87
Makefile
Normal file
@@ -0,0 +1,87 @@
|
||||
# ss-tools test suite
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Tiered test targets designed for agent-driven development:
|
||||
# Tier 1 (fast, <30s): make test
|
||||
# Tier 2 (slow, <5min): make test-integration
|
||||
# Tier 3 (e2e, <10min): make test-e2e
|
||||
#
|
||||
# Smart selection: make test-related F=path/to/file.py
|
||||
# Coverage: make coverage
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
|
||||
ROOT := $(CURDIR)
|
||||
BACKEND := $(ROOT)/backend
|
||||
FRONTEND := $(ROOT)/frontend
|
||||
VENV := $(BACKEND)/.venv/bin/activate
|
||||
|
||||
TIMEOUT_FAST := 120
|
||||
TIMEOUT_SLOW := 600
|
||||
|
||||
.PHONY: help test test-unit test-frontend test-related test-integration test-e2e test-all
|
||||
.PHONY: coverage coverage-backend coverage-frontend
|
||||
.PHONY: lint lint-backend lint-frontend
|
||||
|
||||
# ── Help ───────────────────────────────────────────────────
|
||||
help: ## Show this help message
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
|
||||
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-22s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
# ── Tier 1: Fast tests (no Docker, SQLite + jsdom) ─────────
|
||||
test: test-unit test-frontend ## Run fast unit tests (backend + frontend, <30s)
|
||||
@echo " ✅ All fast tests passed"
|
||||
|
||||
test-unit: ## Run backend unit tests (SQLite, no Docker)
|
||||
@echo " ▶ Backend unit tests (SQLite)..."
|
||||
@cd $(BACKEND) && . $(VENV) && timeout $(TIMEOUT_FAST) python -m pytest tests/ --ignore=tests/integration/ -v --tb=short
|
||||
|
||||
test-frontend: ## Run frontend vitest tests
|
||||
@echo " ▶ Frontend vitest tests..."
|
||||
@cd $(FRONTEND) && npx vitest run
|
||||
|
||||
# ── Tier 2: Smart selection ────────────────────────────────
|
||||
test-related: ## Run tests related to a changed file (make test-related F=path/to/file.py)
|
||||
@if [ -z "$(F)" ]; then echo "Usage: make test-related F=path/to/file.py"; exit 1; fi
|
||||
@echo " ▶ Finding related tests for $(F)..."
|
||||
@python3 $(ROOT)/scripts/find-related-tests.py --file "$(F)" --run
|
||||
|
||||
# ── Tier 3: Slow tests (requires Docker) ───────────────────
|
||||
test-integration: ## Run backend integration tests (Docker + testcontainers)
|
||||
@echo " ▶ Backend integration tests (Docker)..."
|
||||
@cd $(BACKEND) && . $(VENV) && timeout $(TIMEOUT_SLOW) python -m pytest tests/integration/ --run-integration -v --tb=short
|
||||
|
||||
test-e2e: ## Run Playwright E2E tests (requires running app)
|
||||
@echo " ▶ Playwright E2E tests..."
|
||||
@cd $(FRONTEND) && npx playwright test
|
||||
|
||||
# ── Full suite ─────────────────────────────────────────────
|
||||
test-all: ## Run full suite: fast tests + integration (skip installs)
|
||||
@$(MAKE) test
|
||||
@echo ""
|
||||
@echo " ▶ Integration tests (may take several minutes)..."
|
||||
@cd $(BACKEND) && . $(VENV) && timeout $(TIMEOUT_SLOW) python -m pytest tests/integration/ --run-integration -v --tb=short || echo " ⚠ Integration tests skipped (Docker not available or timed out)"
|
||||
@echo ""
|
||||
@echo " ✅ Full test suite complete"
|
||||
|
||||
# ── Coverage ───────────────────────────────────────────────
|
||||
coverage: coverage-backend coverage-frontend ## Generate coverage (backend + frontend)
|
||||
@echo " ✅ Coverage reports ready"
|
||||
@echo " Backend: $(BACKEND)/htmlcov/index.html"
|
||||
@echo " Frontend: $(FRONTEND)/coverage/index.html"
|
||||
|
||||
coverage-backend: ## Backend coverage (unit tests + --cov)
|
||||
@echo " ▶ Backend coverage..."
|
||||
@cd $(BACKEND) && . $(VENV) && timeout $(TIMEOUT_FAST) python -m pytest tests/ --ignore=tests/integration/ \
|
||||
--cov=src --cov-report=term-missing --cov-report=html
|
||||
|
||||
coverage-frontend: ## Frontend coverage (vitest --coverage)
|
||||
@echo " ▶ Frontend coverage..."
|
||||
@cd $(FRONTEND) && npx vitest run --coverage
|
||||
|
||||
# ── Linting ────────────────────────────────────────────────
|
||||
lint: lint-backend lint-frontend ## Run all linters
|
||||
|
||||
lint-backend: ## Backend ruff check
|
||||
@cd $(BACKEND) && . $(VENV) && python -m ruff check .
|
||||
|
||||
lint-frontend: ## Frontend eslint
|
||||
@cd $(FRONTEND) && npx eslint .
|
||||
Reference in New Issue
Block a user