Skip to content

Add uv-managed pytest test foundation#108

Merged
Kris (krisgeus) merged 5 commits into
masterfrom
improve/testing-foundation
Jun 24, 2026
Merged

Add uv-managed pytest test foundation#108
Kris (krisgeus) merged 5 commits into
masterfrom
improve/testing-foundation

Conversation

@krisgeus

Copy link
Copy Markdown
Member

First of three PRs implementing CLAUDE_IMPROVEMENTS.md #4 (Testing Infrastructure). This establishes the shared, uv-managed pytest harness; the DAG-validation and setup-script suites stack on top of it.

What's here

  • pyproject.toml — pins requires-python = ">=3.13,<3.14" (Airflow 3.2.1 doesn't support 3.14) and adds a PEP 735 test dependency group (pytest + Airflow 3.2.1 + curated providers + pendulum/pandas/ephem), plus [tool.pytest.ini_options] and markers.
  • uv.lock — locked resolution for reproducible installs.
  • tests/conftest.py — airflow-free shared anchors (REPO_ROOT, EXAMPLES_DIR, example_dirs_with_dag()) + hermetic Airflow env vars, so lightweight suites run with only pytest.
  • tests/test_foundation.py — smoke tests for a green baseline.
  • CI — a fast, Docker-free unit-tests job (uv sync --group testuv run pytest).
  • CONTRIBUTING.md — documents the uv sync --group test / uv run pytest workflow.

Validation

Local run on Python 3.13: uv sync --group test resolves & installs Airflow 3.2.1, import airflow + DagBag work, uv run pytest is green (2 passed).

Follow-ups (stacked on this branch)

  • Plan A — DAG parsing/validation suite (tests/test_dag_validation.py).
  • Plan B — setup-script shellcheck coverage + convention tests (tests/test_setup_scripts.py).

🤖 Generated with Claude Code

Kris (krisgeus) and others added 2 commits June 21, 2026 22:40
Foundation for CLAUDE_IMPROVEMENTS.md #4 (Testing Infrastructure). Establishes
the shared, uv-managed pytest harness that the DAG-validation (Plan A) and
setup-script (Plan B) suites build on.

- pyproject.toml: pin requires-python to >=3.13,<3.14 (Airflow 3.2.1 does not
  support 3.14) and add a `test` dependency group (pytest + Airflow + the
  curated provider set) plus pytest config and markers.
- uv.lock: locked resolution for reproducible installs.
- tests/conftest.py: airflow-free shared anchors (REPO_ROOT, EXAMPLES_DIR) and
  hermetic Airflow env vars, so lightweight suites run with only pytest.
- tests/test_foundation.py: smoke tests giving the CI job a green baseline.
- .github/workflows/whirl-ci.yml: add a fast, Docker-free `unit-tests` job.
- CONTRIBUTING.md: document the `uv sync --group test` / `uv run pytest` workflow.

Verified locally: `uv sync --group test` resolves and installs Airflow 3.2.1 on
Python 3.13, `import airflow` + DagBag work, and `uv run pytest` is green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the DAG-validation half of CLAUDE_IMPROVEMENTS.md #4, on top of the
uv test foundation.

- tests/test_dag_validation.py: for every examples/*/dag.py, build an Airflow
  DagBag and assert it parses with no import errors and yields >=1 DAG (DagBag
  also enforces unique task ids / no cycles). A second test asserts each dag_id
  stays greppable the way `whirl ci` auto-detects it.
- Explicit SKIP_PARSE map for examples needing packages outside the curated test
  group (dbt-example, dbt-spark-example -> airflow_dbt_python;
  spark-delta-sharing -> delta_sharing) so skips are visible and a new example
  with missing deps fails loudly.
- Two examples import local packages (custom, custom_plugins); validated after
  installing them. CI installs them (mkdir /tmp/custom_build for the timetable
  plugin's egg_base) before running pytest.

Local run: 31 passed, 3 skipped on Python 3.13.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the setup-script half of CLAUDE_IMPROVEMENTS.md #4, on top of the uv
test foundation.

B1 — Fix shellcheck findings in setup scripts so they pass at warning severity:
  - SC1083: `-w ''%{http_code}''` -> `-w '%{http_code}'` (empty-quote pairs left
    the braces unquoted) across the add_connection_* scripts.
  - SC2155: split `local X=$(...)` / `export SPARK_HOME=$(...)` declare+assign.
  - SC2046: quote the `--key` value containing `$(date ...)` in add_mockdata.
  - SC2128: `${BASH_SOURCE}` -> `${BASH_SOURCE[0]}`.
  - SC2044: justified `# shellcheck disable` in the sftp mock-data script
    (controlled, space-free filenames).

B2 — CI: extend the shellcheck job to lint every setup script at
  `--severity=warning` (the main `whirl` script is still linted with `-x`).
  Info-level quoting noise (SC2086) is intentionally deferred.

B3 — tests/test_setup_scripts.py: airflow-free pytest conventions asserting each
  setup script has the bash shebang and NN_name.sh naming, and that every
  whirl.setup.d script enables `set -e` near the top (locking in the Topic 3
  invariant). compose.* scripts are sourced under whirl's own `set -e`, so the
  errexit check is scoped to whirl.setup.d.

Verified: `shellcheck --severity=warning` over all 68 setup scripts is clean;
all modified scripts pass `bash -n`; the pytest conventions suite (191 checks)
passes with a bare pytest (no airflow needed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add setup-script checks: shellcheck-all + pytest conventions (Plan B)
Add DAG parsing & validation test suite (Plan A)
@krisgeus
Kris (krisgeus) merged commit e50773d into master Jun 24, 2026
56 checks passed
@krisgeus
Kris (krisgeus) deleted the improve/testing-foundation branch June 24, 2026 06:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant