Skip to content

Add unit tests for the FAB app-init extensions - #72986

Closed
ShousenZHANG wants to merge 1 commit into
apache:mainfrom
ShousenZHANG:fab-ext-tests
Closed

ShousenZHANG wants to merge 1 commit into
apache:mainfrom
ShousenZHANG:fab-ext-tests

Conversation

@ShousenZHANG

@ShousenZHANG ShousenZHANG commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Five of the seven providers/fab/src/airflow/providers/fab/www/extensions/ modules are listed in OVERLOOKED_TESTS with no tests at all, and create_app() reaches all five while building the Flask app: configure_manifest_files at www/app.py:113 and init_api_auth at :114, then init_error_handlers at :118, init_plugins at :127 (only when enable_plugins), init_jinja_globals at :130 and init_wsgi_middleware at :131 inside the app_context opened at :116. Nothing in create_app catches, so a failure in any of them stops the app from starting; a silent behaviour change in init_wsgi_middleware or init_jinja_globals instead alters what gets served.

Grouped into one PR per the request on #35442 — "Batch a provider's worth of missing test modules into a single PR instead."

What the tests pin

module pinned behaviour
init_wsgi_middlewares the five [fab] proxy_fix_x_* options set to five distinct values, so a mix-up between the five near-identical ProxyFix keyword arguments fails; wsgi_app untouched when the option is off
init_security the comma split and per-entry strip, import order, the default backend, and ImportError → AirflowException
init_jinja_globals the three default_timezone branches incl. the non-callable guard, hostname redaction when [fab] expose_hostname is off, the four navbar colours, and the two opposite globals driven by enable_plugins
init_manifest_files the dist/ prefixing, the fallback to the raw filename when the manifest is missing or the key unknown, the debug-mode re-read
init_views view not forwarded twice for named views, add_view_no_menu for unnamed ones, the named-view-without-a-view log, blueprint registration, the 500/404 handler pair

One behaviour is recorded rather than asserted as correct: an empty [fab] auth_backends makes init_api_auth call import_module(""), which raises ValueError, and the function's except ImportError does not catch it — so it escapes as a bare ValueError instead of the AirflowException every other bad backend produces. The test documents that; fixing it belongs in a change to the module, not here.

Mutation results

Assertion count says nothing about whether a test can fail, so each of the five modules was broken one line at a time. 22 of 22 mutations are caught:

  • init_wsgi_middlewares (4/4) — x_host reading PROXY_FIX_X_PORT; dropping the x_prefix= keyword; inverting the ENABLE_PROXY_FIX guard; hardcoding x_for=1
  • init_security (4/4) — dropping .strip(); swallowing the ImportError; not appending to app.api_auth; widening except ImportError to except Exception
  • init_jinja_globals (6/6) — not upper-casing utc; dropping the non-callable local_timezone guard; inverting the hostname redaction; swapping two navbar colours; un-inverting disable_nav_bar; letting the version lookup raise
  • init_manifest_files (4/4) — dropping the dist/ prefix; narrowing the bare except; removing the debug re-read; ignoring the manifest lookup
  • init_views (4/4) — forwarding the whole view dict to add_view; using add_view for unnamed views; swapping the 500/404 handlers; skipping blueprint registration

Scope and conflicts

This clears 5 of the 7 fab/www/extensions exemptions. The two left are init_appbuilder (615 lines, needs a real AirflowAppBuilder) and init_session, which #72825 already covers.

Two things a reviewer should know:

init_plugins' pre-3.1/pre-3.2 branches are unreachable on main (AIRFLOW_V_3_1_PLUS and AIRFLOW_V_3_2_PLUS are both true) and are not covered; TestInitPlugins carries a matching skipif.

Verification

  • pytest providers/fab/tests/unit/fab/www/extensions/ — 27 passed
  • pytest airflow-core/tests/unit/always/test_project_structure.py — 10 passed, 1 pre-existing xfail
  • ruff check and ruff format --check — clean
  • prek run --files <the 8 changed files> — 0 failed
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code

Generated-by: Claude Code following the guidelines

The tests were written by an AI assistant. I checked the call sites in www/app.py, ran the 22 mutations above to confirm every test can actually fail, and ran the commands under Verification.

Copilot AI lite review requested due to automatic review settings September 11, 2026 16:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Five of the seven `providers/fab/.../www/extensions/` modules were listed in
`OVERLOOKED_TESTS` with no tests at all, and `create_app()` calls all five while
building the Flask app, so a regression in any of them either stops the app from
starting or silently changes what it serves.

What the tests pin, per module:

- `init_wsgi_middlewares`: the five `[fab] proxy_fix_x_*` options are set to five
  distinct values, so a mix-up between the five near-identical `ProxyFix` keyword
  arguments fails; and `wsgi_app` is left untouched when the option is off.
- `init_security`: the comma split and per-entry strip, the import order, the
  default backend, and `ImportError` becoming `AirflowException`. An empty
  `auth_backends` raises `ValueError` instead, which `except ImportError` does not
  catch - recorded as current behaviour.
- `init_jinja_globals`: the three `default_timezone` branches including the
  non-callable guard, hostname redaction when `[fab] expose_hostname` is off, the
  four navbar colours, and the two opposite globals driven by `enable_plugins`.
- `init_manifest_files`: the `dist/` prefixing, the fallback to the raw filename
  when the manifest is missing or the key is unknown, and the debug-mode re-read.
- `init_views`: `view` not being forwarded twice for named views,
  `add_view_no_menu` for unnamed ones, the named-view-without-a-view log, blueprint
  registration, and the 500/404 handler pair.

Verified by mutation rather than by assertion count: 22 one-line breakages of the
five modules were each applied in turn, and all 22 make the new tests fail.

Drops the five matching paths from `OVERLOOKED_TESTS`, leaving `init_appbuilder`
(615 lines, its own PR) and `init_session` (already covered by #72825).

Generated-by: Claude Code
@ShousenZHANG ShousenZHANG changed the title Add unit tests for the FAB WSGI middleware and API auth initialisers Add unit tests for the FAB app-init extensions Sep 11, 2026
@vincbeck

Copy link
Copy Markdown
Contributor

The issue has been closed, no need to add all these tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants