|
2 | 2 | SHELL := /bin/bash |
3 | 3 | export PATH := $(HOME)/.local/bin:$(HOME)/.cargo/bin:$(PATH) |
4 | 4 |
|
| 5 | +# Export test configuration variables so they're available to child processes |
| 6 | +# Usage: make test STRESS_TEST_MODE=moderate PYTEST_ARGS="-v" |
| 7 | +# make test LOG=info (adds --log-cli-level=INFO to default PYTEST_ARGS) |
| 8 | +export STRESS_TEST_MODE |
| 9 | +export DGRAPH_IMAGE_TAG |
| 10 | + |
| 11 | +# When LOG is set (e.g., LOG=info), inject --log-cli-level into pytest flags. |
| 12 | +# Works with both the default PYTEST_ARGS and explicit overrides: |
| 13 | +# make test LOG=info → -v --benchmark-disable --log-cli-level=INFO |
| 14 | +# make benchmark LOG=warning → --benchmark-only ... --log-cli-level=WARNING |
| 15 | +# make test PYTEST_ARGS="-x" LOG=debug → -x --log-cli-level=DEBUG |
| 16 | +PYTEST_ARGS ?= -v --benchmark-disable |
| 17 | +ifdef LOG |
| 18 | + LOG_FLAG := --log-cli-level=$(shell echo '$(LOG)' | tr '[:lower:]' '[:upper:]') |
| 19 | + PYTEST_ARGS += $(LOG_FLAG) |
| 20 | +endif |
| 21 | +export LOG |
| 22 | +export PYTEST_ARGS |
| 23 | + |
5 | 24 | # Source venv if it exists and isn't already active |
6 | 25 | PROJECT_VENV := $(CURDIR)/.venv |
7 | 26 | ACTIVATE := $(wildcard .venv/bin/activate) |
|
15 | 34 | RUN := |
16 | 35 | endif |
17 | 36 |
|
18 | | -.PHONY: help setup sync deps deps-uv deps-trunk deps-docker test check protogen clean build publish |
| 37 | +.PHONY: help setup sync deps deps-uv deps-trunk deps-docker test benchmark check protogen clean build publish |
19 | 38 |
|
20 | 39 | .DEFAULT_GOAL := help |
21 | 40 |
|
22 | 41 | help: ## Show this help message |
23 | 42 | @echo "" |
24 | 43 | @echo "Environment Variables:" |
25 | 44 | @echo " INSTALL_MISSING_TOOLS=true Enable automatic installation of missing tools (default: disabled)" |
| 45 | + @echo " LOG=<level> Add --log-cli-level to pytest (e.g., LOG=info, LOG=debug)" |
| 46 | + @echo " Works with both 'test' and 'benchmark' targets" |
| 47 | + @echo " STRESS_TEST_MODE=<mode> Stress test preset: quick (default), moderate, full" |
| 48 | + @echo " PYTEST_ARGS=\"...\" Override default pytest flags (default: -v --benchmark-disable)" |
| 49 | + @echo " Note: overrides LOG when set explicitly. 'benchmark' sets its own" |
| 50 | + @echo " PYTEST_ARGS internally but still honours LOG" |
| 51 | + @echo " DGRAPH_IMAGE_TAG=<tag> Override the Dgraph Docker image tag (default: latest)" |
26 | 52 | @echo "" |
27 | 53 | @echo "Available targets:" |
28 | 54 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' |
@@ -51,8 +77,31 @@ clean: ## Cleans build artifacts |
51 | 77 | build: deps-uv sync protogen ## Builds release package |
52 | 78 | $(RUN) uv build |
53 | 79 |
|
54 | | -test: deps-uv sync ## Run tests |
55 | | - bash scripts/local-test.sh |
| 80 | +test: deps-uv sync ## Run tests (use PYTEST_ARGS to pass options, e.g., make test PYTEST_ARGS="-v tests/test_connect.py") |
| 81 | + bash scripts/local-test.sh $(PYTEST_ARGS) |
| 82 | + |
| 83 | +benchmark: ## Run benchmarks (measures per-operation latency with pytest-benchmark) |
| 84 | + @# Outputs (all .gitignored): |
| 85 | + @# benchmark-results.json Phase 1 results (pytest-benchmark JSON) |
| 86 | + @# benchmark-histogram.svg Phase 1 latency histogram |
| 87 | + @# stress-benchmark-results.json Phase 2 results (pytest-benchmark JSON) |
| 88 | + @# |
| 89 | + @# Phase 1: Per-operation latency benchmarks against a clean database. |
| 90 | + @# Runs targeted benchmark tests (test_benchmark_*.py) which measure individual |
| 91 | + @# operations (query, mutation, upsert, etc.) in isolation. Each test creates a |
| 92 | + @# fresh schema via drop_all, so these MUST run on their own Dgraph cluster — |
| 93 | + @# the rapid schema churn destabilises the alpha for any tests that follow. |
| 94 | + @echo "═══ Phase 1: Per-operation latency benchmarks ═══" |
| 95 | + $(MAKE) test PYTEST_ARGS="--benchmark-only --benchmark-json=benchmark-results.json --benchmark-histogram=benchmark-histogram -v $(LOG_FLAG) tests/test_benchmark_async.py tests/test_benchmark_sync.py" |
| 96 | + @# Phase 2: Stress-test benchmarks under sustained concurrent load. |
| 97 | + @# Runs stress tests (test_stress_*.py) with the 1-million-movie dataset loaded. |
| 98 | + @# Uses a separate Dgraph cluster (via a second 'make test' invocation) so the |
| 99 | + @# alpha starts fresh after Phase 1's drop_all churn. |
| 100 | + @# benchmark.pedantic(rounds=1) in each stress test prevents pytest-benchmark |
| 101 | + @# from compounding iterations — the stress_config["rounds"] inner loop |
| 102 | + @# (controlled by STRESS_TEST_MODE) handles repetition instead. |
| 103 | + @echo "═══ Phase 2: Stress-test benchmarks (moderate load, 1M movies) ═══" |
| 104 | + $(MAKE) test STRESS_TEST_MODE=moderate PYTEST_ARGS="--benchmark-only --benchmark-json=stress-benchmark-results.json -v $(LOG_FLAG) tests/test_stress_async.py tests/test_stress_sync.py" |
56 | 105 |
|
57 | 106 | publish: clean build ## Publish a new release to PyPi (requires UV_PUBLISH_USERNAME and UV_PUBLISH_PASSWORD to be set) |
58 | 107 | $(RUN) uv publish |
|
0 commit comments