Skip to content

Commit b7d051c

Browse files
test: add staged pytest integration suite
1 parent 89f8083 commit b7d051c

14 files changed

Lines changed: 683 additions & 3 deletions

AGENTS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ make build-databricks # Databricks Connect
8181

8282
# Run tests
8383
poetry run pytest tests/unit/
84+
make test-integration # Staged pytest integration suite (seed -> search -> eval)
85+
make test-integration-verbose # Same suite with live test logs in terminal
8486

8587
# Format and lint
8688
poetry run black .

CONTRIBUTING.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,21 @@ To set up the development environment:
9191
poetry run pytest
9292
```
9393

94+
4. **Run staged integration tests before opening a PR**:
95+
96+
```bash
97+
# Requires ANTHROPIC_API_KEY and local Spark/Java setup
98+
bash scripts/tests/run_integration_staged.sh
99+
```
100+
101+
The staged suite runs three pytest phases with hard barriers:
102+
- `integration_seed`: builds reusable checkpoints through phase 3
103+
- `integration_search`: resumes from seeds and runs model search
104+
- `integration_eval`: resumes from search checkpoints, runs evaluation, and validates predictor inference
105+
106+
This `tests/integration` suite is the primary pre-PR integration workflow.
107+
Makefile Docker targets remain optional/manual end-to-end checks.
108+
94109
Ensure all tests pass before making contributions.
95110

96111
## Style Guides

Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
# Quick reference for developers:
55
# make help Show all available commands
66
# make test-quick Fast test (~30s, 1 iteration)
7+
# make test-integration Staged pytest integration suite
8+
# make test-integration-verbose Staged suite with live logs
79
# make test-xgboost Test XGBoost only
810
# make test-catboost Test CatBoost only
911
# make test-all-models Test all model types
@@ -36,6 +38,8 @@ help:
3638
@echo " make test-lightgbm Test LightGBM model type"
3739
@echo " make test-pytorch Test PyTorch model type"
3840
@echo " make test-keras Test Keras model type"
41+
@echo " make test-integration Run staged pytest integration suite"
42+
@echo " make test-integration-verbose Run staged suite with live logs"
3943
@echo " make test-all-models Test all model types (sequential)"
4044
@echo " make test-full Full test run (3 iterations + evaluation)"
4145
@echo ""
@@ -61,6 +65,28 @@ help:
6165
# Quick Development Tests
6266
# ============================================
6367

68+
# Staged pytest-native integration suite (seed -> search -> eval).
69+
# Optional: make test-integration INTEGRATION_RUN_ID=my_run_id
70+
.PHONY: test-integration
71+
test-integration:
72+
@echo "🧪 Running staged pytest integration suite..."
73+
@if [ -n "$(INTEGRATION_RUN_ID)" ]; then \
74+
echo "Using integration run id: $(INTEGRATION_RUN_ID)"; \
75+
PLEXE_IT_RUN_ID="$(INTEGRATION_RUN_ID)" bash scripts/tests/run_integration_staged.sh; \
76+
else \
77+
bash scripts/tests/run_integration_staged.sh; \
78+
fi
79+
80+
.PHONY: test-integration-verbose
81+
test-integration-verbose:
82+
@echo "🧪 Running staged pytest integration suite (verbose)..."
83+
@if [ -n "$(INTEGRATION_RUN_ID)" ]; then \
84+
echo "Using integration run id: $(INTEGRATION_RUN_ID)"; \
85+
PLEXE_IT_RUN_ID="$(INTEGRATION_RUN_ID)" PLEXE_IT_VERBOSE=1 bash scripts/tests/run_integration_staged.sh; \
86+
else \
87+
PLEXE_IT_VERBOSE=1 bash scripts/tests/run_integration_staged.sh; \
88+
fi
89+
6490
# Fast sanity check - 1 iteration, minimal config
6591
.PHONY: test-quick
6692
test-quick: build

poetry.lock

Lines changed: 37 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,21 @@ vision = ["torch"]
8484

8585
[tool.poetry.group.dev.dependencies]
8686
pytest = "^8.3.4"
87+
pytest-xdist = "^3.8.0"
8788
pre-commit = "^4.0.1"
8889
ruff = "^0.14.9"
8990
black = ">=23.0.0"
9091
streamlit = ">=1.52.1,<2.0.0"
9192
plotly = ">=6.5.0,<7.0.0"
9293
boto3 = "^1.42.44"
9394

95+
[tool.pytest.ini_options]
96+
markers = [
97+
"integration_seed: stage 1 integration tests that build reusable checkpoints through phase 3",
98+
"integration_search: stage 2 integration tests that resume from seeds and pause after phase 4",
99+
"integration_eval: stage 3 integration tests that resume from search checkpoints and run evaluation + packaging",
100+
]
101+
94102
[tool.semantic_release]
95103
version_variables = ["pyproject.toml:version"]
96104
commit_parser = "angular"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5+
cd "$ROOT_DIR"
6+
7+
if [[ -z "${PLEXE_IT_RUN_ID:-}" ]]; then
8+
PLEXE_IT_RUN_ID="$(date +%Y%m%d_%H%M%S)"
9+
fi
10+
export PLEXE_IT_RUN_ID
11+
12+
ARTIFACT_ROOT="$ROOT_DIR/.pytest_cache/integration/$PLEXE_IT_RUN_ID"
13+
mkdir -p "$ARTIFACT_ROOT"
14+
15+
if ! poetry run python -c "import importlib.util,sys; sys.exit(0 if importlib.util.find_spec('xdist') else 1)"; then
16+
echo "ERROR: pytest-xdist is required for staged integration tests."
17+
echo "Install dependencies with: poetry install"
18+
echo "Then verify with: poetry run pytest --help | grep -E '(^| )-n( |$)'"
19+
exit 2
20+
fi
21+
22+
if [[ -n "${PLEXE_IT_WORKERS:-}" ]]; then
23+
WORKERS="${PLEXE_IT_WORKERS}"
24+
elif [[ "${PLEXE_IT_VERBOSE:-0}" == "1" ]]; then
25+
# In verbose mode, default to main-process execution for reliable live logs.
26+
WORKERS="0"
27+
else
28+
WORKERS="auto"
29+
fi
30+
PYTEST_PARALLEL_ARGS=(-n "$WORKERS")
31+
32+
run_stage() {
33+
local stage_name="$1"
34+
local marker="$2"
35+
local cmd=(poetry run pytest tests/integration -m "$marker" "${PYTEST_PARALLEL_ARGS[@]}" --maxfail=1)
36+
37+
if [[ "${PLEXE_IT_VERBOSE:-0}" == "1" ]]; then
38+
cmd+=(-s -vv -o log_cli=true -o log_cli_level=INFO --capture=tee-sys)
39+
fi
40+
41+
PLEXE_IT_STAGE="$stage_name" "${cmd[@]}"
42+
}
43+
44+
echo "Running staged integration tests with run id: $PLEXE_IT_RUN_ID"
45+
echo "Artifacts: $ARTIFACT_ROOT"
46+
echo "Workers: $WORKERS"
47+
if [[ "${PLEXE_IT_VERBOSE:-0}" == "1" ]]; then
48+
echo "Verbose mode: enabled (live logs and test output)"
49+
fi
50+
51+
echo ""
52+
echo "Stage 1/3: building reusable seeds through phase 3"
53+
run_stage "seed" "integration_seed"
54+
55+
echo ""
56+
echo "Stage 2/3: resuming from seeds through phase 4"
57+
run_stage "search" "integration_search"
58+
59+
echo ""
60+
echo "Stage 3/3: final evaluation, packaging, and predictor checks"
61+
run_stage "eval" "integration_eval"
62+
63+
echo ""
64+
echo "Staged integration suite completed successfully."

tests/CODE_INDEX.md

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,48 @@
44
55
Test suite structure and test case documentation.
66

7-
## `integration/test_feedback.py`
7+
## `integration/conftest.py`
8+
Shared fixtures and helpers for staged integration tests.
9+
10+
**Functions:**
11+
- `repo_root() -> Path` - Return repository root path.
12+
- `run_id() -> str` - Return deterministic run identifier for staged artifacts.
13+
- `artifact_root(repo_root: Path, run_id: str) -> Path` - Return base path for staged integration artifacts.
14+
- `configure_integration_environment(repo_root: Path) -> None` - Set environment variables needed by the integration suite.
15+
- `cleanup_spark_session() -> None` - Stop Spark session after tests complete.
16+
- `seed_path(artifact_root: Path, dataset_kind: str) -> Path` - Return seed directory path for a dataset kind.
17+
- `model_run_path(artifact_root: Path, model_type: str) -> Path` - Return model-specific run directory path.
18+
- `checkpoint_file(work_dir: Path, phase_name: str) -> Path` - Return path to a checkpoint file.
19+
- `copy_seed_to_model_run(seed_dir: Path, model_dir: Path) -> None` - Copy a seed workdir into a model run workdir and rewrite checkpoint paths.
20+
- `assert_stage_prereqs(stage: str, artifact_root: Path) -> None` - Assert required artifacts from prior stages exist.
21+
- `build_seed_workflow(work_dir: Path, dataset_input: Path, intent: str, experiment_id: str) -> Any` - Run stages 1-3 and pause after baseline creation.
22+
- `resume_workflow(work_dir: Path, allowed_model_types: list[str], pause_points: list[str] | None, enable_final_evaluation: bool, max_iterations: int) -> Any` - Resume a staged integration workflow from existing checkpoints.
23+
- `load_predictor_class(model_dir: Path, model_type: str) -> type` - Load predictor class from packaged model/predictor.py.
24+
- `load_prediction_input(repo_root: Path, dataset_kind: str, n_rows: int) -> pd.DataFrame` - Load a small feature sample used for predictor checks.
25+
26+
---
27+
## `integration/test_stage1_seed.py`
28+
Stage 1 integration tests: build reusable checkpoints through phase 3.
29+
30+
**Functions:**
31+
- `test_build_seed_checkpoint(dataset_kind: str, artifact_root, repo_root) -> None` - Build a seed run and pause after baseline creation.
32+
33+
---
34+
## `integration/test_stage2_search.py`
35+
Stage 2 integration tests: resume from seeds and pause after phase 4.
36+
37+
**Functions:**
38+
- `test_resume_from_seed_and_run_search_only(model_type: str, artifact_root) -> None` - Copy a seed, resume from checkpoints, and pause after search models.
39+
40+
---
41+
## `integration/test_stage3_eval_predict.py`
42+
Stage 3 integration tests: run evaluation/packaging and validate predictors.
43+
44+
**Functions:**
45+
- `test_resume_and_run_eval_then_predict(model_type: str, artifact_root, repo_root) -> None` - Resume from stage 2 checkpoints, run to completion, and validate predictor inference.
46+
47+
---
48+
## `unit/agents/test_feedback.py`
849
Tests for user feedback integration in agents.
950

1051
**`TestFeedbackFormatting`** - Test the format_user_feedback_for_prompt helper function.

0 commit comments

Comments
 (0)