# Testing signals — pallets/flask

> Canonical page: https://codevetter.com/unpack/flask/testing-signals

# Testing signals — pallets/flask

Scanned commit d73fa1cdcbd8b1465c151db8924ba58b1dd14e35 (2026-09-08). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Testing is pytest-only, rooted at `tests/` with `testpaths = ["tests"]` and `filterwarnings = ["error"]` so any unexpected warning fails the suite — a notable constraint given 3.2's new deprecation warnings. 22 test modules totalling ~7.6k lines cover the framework, with `test_basic.py` (1974 lines, 95 tests), `test_blueprints.py` (1115) and `test_cli.py` (703) dominating. Fixtures in `conftest.py` provide `app`, `client`, `app_ctx`, `req_ctx`, plus two autouse guards: `_standard_os_environ` clears FLASK_* env vars, and `leak_detector` asserts no app context is left pushed at test end. Static typing is treated as a test surface of its own: `tests/type_check/` holds three assertion-free modules checked by strict mypy and pyright in a dedicated CI job. Coverage is configured with branch mode over `flask` and `tests`, but no coverage gate is enforced in any workflow.
- pytest config is minimal and strict: `testpaths = ["tests"]` with `filterwarnings = ["error"]`, so every warning — including the new `RequestContext`/`should_ignore_error` DeprecationWarnings — must be explicitly expected by a test. — [pyproject.toml#L90-L94](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/pyproject.toml#L90-L94) [src/flask/ctx.py#L528-L538](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/ctx.py#L528-L538) [src/flask/app.py#L1001-L1012](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L1001-L1012)
- `tests/conftest.py` defines an autouse `leak_detector` that pops every still-pushed `app_ctx` after each test and asserts the leak list is empty — a hard guard against context-management regressions. — [tests/conftest.py#L67-L79](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/conftest.py#L67-L79)
- The autouse `_standard_os_environ` fixture monkeypatch-deletes `FLASK_ENV_FILE`, `FLASK_APP`, `FLASK_DEBUG`, `FLASK_RUN_FROM_CLI` and `WERKZEUG_RUN_MAIN` so CLI tests can't leak environment state into each other. — [tests/conftest.py#L10-L24](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/conftest.py#L10-L24)
- The shared `app` fixture builds `Flask("flask_test", root_path=os.path.dirname(__file__))` with `TESTING=True` and `SECRET_KEY="test key"`, which is why `tests/templates/` and `tests/static/` resolve as the app's template and static folders. — [tests/conftest.py#L27-L34](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/conftest.py#L27-L34) [tests/templates/simple_template.html](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/templates/simple_template.html) [tests/static/index.html](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/static/index.html)
- Test weight is concentrated: `test_basic.py` 1974 lines / 95 test functions, `test_blueprints.py` 1115, `test_cli.py` 703 / 34 tests, `test_templating.py` 532 — versus 28 lines for `test_session_interface.py` and 21 for `test_subclassing.py`. — [tests/test_basic.py](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_basic.py) [tests/test_blueprints.py](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_blueprints.py) [tests/test_cli.py](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_cli.py) [tests/test_session_interface.py](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_session_interface.py)
- CLI tests are backed by fixture apps under `tests/test_apps/`, including `cliapp/factory.py`, `cliapp/multiapp.py`, `cliapp/importerrorapp.py`, a nested `inner1/inner2/flask.py` shadowing case, and `helloworld/wsgi.py` for implicit discovery — plus checked-in `.env` and `.flaskenv` files. — [tests/test_apps/cliapp/factory.py](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_apps/cliapp/factory.py) [tests/test_apps/cliapp/multiapp.py](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_apps/cliapp/multiapp.py) [tests/test_apps/helloworld/wsgi.py](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_apps/helloworld/wsgi.py) [tests/test_apps/.flaskenv](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_apps/.flaskenv)
- Async coverage is gated on the optional extra: `tests/test_async.py` begins with `pytest.importorskip("asgiref")` and exercises async views, async `View.dispatch_request`, async `MethodView` handlers and async error handlers across app and blueprint. — [tests/test_async.py#L1-L40](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_async.py#L1-L40) [pyproject.toml#L31-L32](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/pyproject.toml#L31-L32)
- Type checking is a first-class test target: `tests/type_check/` contains `typing_route.py`, `typing_app_decorators.py` and `typing_error_handler.py`, and both mypy (`strict = true`, `files = ["src", "tests/type_check"]`) and pyright run over them in the `typing` tox env and a dedicated CI job. — [tests/type_check/typing_route.py#L1-L25](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/type_check/typing_route.py#L1-L25) [pyproject.toml#L114-L131](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/pyproject.toml#L114-L131) [.github/workflows/tests.yaml#L44-L66](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/.github/workflows/tests.yaml#L44-L66)
- The test matrix is unusually broad: CPython 3.10–3.15 including free-threaded `3.14t`, Windows and macOS runners, PyPy 3.11, a minimum-dependency env pinning exact lower bounds, and a dev env installing six Pallets libraries from git main tarballs. — [.github/workflows/tests.yaml#L14-L32](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/.github/workflows/tests.yaml#L14-L32) [pyproject.toml#L176-L210](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/pyproject.toml#L176-L210)
- Coverage is configured (branch mode, `source = ["flask", "tests"]`, `exclude_also` for TYPE_CHECKING blocks and `raise NotImplementedError`) but no workflow runs coverage or enforces a threshold — the tox commands invoke plain `pytest -v --tb=short`. — [pyproject.toml#L96-L112](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/pyproject.toml#L96-L112) [pyproject.toml#L166-L174](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/pyproject.toml#L166-L174) [.github/workflows/tests.yaml#L41-L43](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/.github/workflows/tests.yaml#L41-L43)
- Example apps carry their own tests: `examples/tutorial/tests/` has four modules (auth, blog, db, factory) plus `data.sql` seed data, and `examples/javascript/tests/test_js_example.py` exists — but neither is in `testpaths`, so CI never runs them. — [examples/tutorial/tests/test_auth.py](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/examples/tutorial/tests/test_auth.py) [examples/tutorial/tests/data.sql](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/examples/tutorial/tests/data.sql) [examples/javascript/tests/test_js_example.py](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/examples/javascript/tests/test_js_example.py) [pyproject.toml#L90-L91](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/pyproject.toml#L90-L91)
- Session security behaviour has direct tests — SameSite attribute variants and `SECRET_KEY_FALLBACKS` key rotation are asserted in `test_basic.py` around lines 342–420. — [tests/test_basic.py#L342-L420](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/tests/test_basic.py#L342-L420) [src/flask/sessions.py#L303-L322](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/sessions.py#L303-L322)
- Test harness code being tested is itself shipped: `FlaskClient.session_transaction` opens a real request context, mutates the session, saves it and re-injects `Set-Cookie` into the client jar, and `FlaskCliRunner.invoke` defaults `obj` to `ScriptInfo(create_app=lambda: self.app)`. — [src/flask/testing.py#L135-L183](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/testing.py#L135-L183) [src/flask/testing.py#L262-L298](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/testing.py#L262-L298)
- Style enforcement runs via pre-commit (ruff check + ruff format, uv-lock, codespell, merge-conflict/debug-statement/whitespace hooks) with all revs pinned to frozen SHAs, executed both as the `style` tox env and the `pre-commit.yaml` workflow. — [.pre-commit-config.yaml#L1-L26](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/.pre-commit-config.yaml#L1-L26) [pyproject.toml#L211-L216](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/pyproject.toml#L211-L216)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
