From 1d8b2996049ab51deb544713801f1544e624e593 Mon Sep 17 00:00:00 2001 From: robotrocketscience Date: Sun, 26 Apr 2026 18:50:56 -0700 Subject: [PATCH] build: add pytest-timeout with 5s default and registered markers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds pytest-timeout to dev deps and configures a 5s default wall-clock timeout for every collected test. Per project test policy: every test must deterministically terminate via pass, fail, error, or timeout — no hangs, no flakes. Subprocess-driven CLI/MCP integration tests arriving in v0.6.0+ override the default per-test via @pytest.mark.timeout(N). Also enables strict_markers and registers two custom markers used by the upcoming regression suite (v0.4.0+) and the v0.9.0-rc UAT gate: - regression: cumulative integration scenarios - uat: v1.0 acceptance-criteria tests Local verification: 32 tests pass in 0.04s under the new config. --- pyproject.toml | 10 ++++++++++ uv.lock | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 70f124104..b70f36914 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ dependencies = [] [project.optional-dependencies] dev = [ "pytest>=8.0", + "pytest-timeout>=2.3", "pyright>=1.1.409", ] @@ -22,6 +23,15 @@ packages = ["src/aelfrice"] [tool.pytest.ini_options] testpaths = ["tests"] +# Test policy: every test must deterministically terminate. 5s default +# wall-clock timeout for unit/property tests. Subprocess-driven CLI/MCP +# integration tests (v0.6.0+) override per-test via @pytest.mark.timeout(N). +timeout = 5 +strict_markers = true +markers = [ + "regression: cumulative integration scenarios run alongside the unit suite", + "uat: v1.0 acceptance-criteria tests, run as the final pre-tag gate", +] [tool.pyright] include = ["src/aelfrice", "tests"] diff --git a/uv.lock b/uv.lock index a48889b88..6e70085d4 100644 --- a/uv.lock +++ b/uv.lock @@ -11,12 +11,14 @@ source = { editable = "." } dev = [ { name = "pyright" }, { name = "pytest" }, + { name = "pytest-timeout" }, ] [package.metadata] requires-dist = [ { name = "pyright", marker = "extra == 'dev'", specifier = ">=1.1.409" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" }, + { name = "pytest-timeout", marker = "extra == 'dev'", specifier = ">=2.3" }, ] provides-extras = ["dev"] @@ -103,6 +105,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, ] +[[package]] +name = "pytest-timeout" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/82/4c9ecabab13363e72d880f2fb504c5f750433b2b6f16e99f4ec21ada284c/pytest_timeout-2.4.0.tar.gz", hash = "sha256:7e68e90b01f9eff71332b25001f85c75495fc4e3a836701876183c4bcfd0540a", size = 17973, upload-time = "2025-05-05T19:44:34.99Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl", hash = "sha256:c42667e5cdadb151aeb5b26d114aff6bdf5a907f176a007a30b940d3d865b5c2", size = 14382, upload-time = "2025-05-05T19:44:33.502Z" }, +] + [[package]] name = "typing-extensions" version = "4.15.0"