Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ site/ # Astro landing page (synthorg.io)
- **Parallelism**: `pytest-xdist` via `-n auto` — **ALWAYS** include `-n auto` when running pytest, never run tests sequentially
- **Parametrize**: Prefer `@pytest.mark.parametrize` for testing similar cases
- **Vendor-agnostic everywhere**: NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples. Use generic names: `example-provider`, `example-large-001`, `example-medium-001`, `example-small-001`, `large`/`medium`/`small` as aliases. Vendor names may only appear in: (1) Operations design page provider list (`docs/design/operations.md`), (2) `.claude/` skill/agent files, (3) third-party import paths/module names (e.g. `litellm.types.llms.openai`). Tests must use `test-provider`, `test-small-001`, etc.
- **Property-based testing**: Python uses [Hypothesis](https://hypothesis.readthedocs.io/) (`@given` + `@settings`), Vue uses [fast-check](https://fast-check.dev/) (`fc.assert` + `fc.property`), Go uses native `testing.F` fuzz functions (`Fuzz*`). Hypothesis profiles: `ci` (200 examples, default) and `dev` (1000 examples), controlled via `HYPOTHESIS_PROFILE` env var. Run dev profile: `HYPOTHESIS_PROFILE=dev uv run python -m pytest tests/ -m unit -n auto -k properties`. `.hypothesis/` is gitignored.
- **Property-based testing**: Python uses [Hypothesis](https://hypothesis.readthedocs.io/) (`@given` + `@settings`), Vue uses [fast-check](https://fast-check.dev/) (`fc.assert` + `fc.property`), Go uses native `testing.F` fuzz functions (`Fuzz*`). Hypothesis profiles: `ci` (50 examples, default) and `dev` (1000 examples), controlled via `HYPOTHESIS_PROFILE` env var. Run dev profile: `HYPOTHESIS_PROFILE=dev uv run python -m pytest tests/ -m unit -n auto -k properties`. `.hypothesis/` is gitignored.
- **Flaky tests**: NEVER skip, dismiss, or ignore flaky tests — always fix them fully and fundamentally. For timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins.

## Git
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

settings.register_profile(
"ci",
max_examples=200,
max_examples=50,
suppress_health_check=[HealthCheck.too_slow],
)
settings.register_profile(
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/communication/test_bus_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ async def receiver() -> None:
received.append(result)

async def unsubscriber() -> None:
await asyncio.sleep(0.05)
await asyncio.sleep(0)
await bus.unsubscribe("#general", "agent-a")

async with asyncio.TaskGroup() as tg:
Expand All @@ -302,7 +302,7 @@ async def receiver() -> None:
received.append(result)

async def unsubscriber() -> None:
await asyncio.sleep(0.05)
await asyncio.sleep(0)
await bus.unsubscribe("#general", "agent-a")

async with asyncio.TaskGroup() as tg:
Expand Down Expand Up @@ -395,7 +395,7 @@ async def receiver() -> None:
received.append(envelope.message.content)

async def publisher() -> None:
await asyncio.sleep(0.05)
await asyncio.sleep(0)
msg = _make_message(channel="#general", content="delayed")
await bus.publish(msg)

Expand Down Expand Up @@ -673,7 +673,7 @@ async def test_receive_returns_none_on_shutdown(self) -> None:
await bus.subscribe("#general", "agent-a")

async def stop_after_delay() -> None:
await asyncio.sleep(0.05)
await asyncio.sleep(0)
await bus.stop()

async with asyncio.TaskGroup() as tg:
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/communication/test_dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,12 @@ async def test_handlers_run_concurrently(self) -> None:

async def _slow(msg: Message) -> None:
order.append("slow-start")
await asyncio.sleep(0.05)
await asyncio.sleep(0)
order.append("slow-end")

async def _fast(msg: Message) -> None:
order.append("fast-start")
await asyncio.sleep(0.01)
await asyncio.sleep(0)
order.append("fast-end")

dispatcher = MessageDispatcher()
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/engine/test_parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ async def track_concurrency(**kwargs: object) -> AgentRunResult:
async with lock:
current_concurrent += 1
max_concurrent = max(max_concurrent, current_concurrent)
await asyncio.sleep(0.05)
await asyncio.sleep(0)
async with lock:
current_concurrent -= 1
identity = kwargs.get("identity")
Expand Down Expand Up @@ -653,7 +653,7 @@ async def test_in_progress_respects_concurrency_limit(self) -> None:
max_in_progress = 0

async def track_concurrency(**kwargs: object) -> AgentRunResult:
await asyncio.sleep(0.05)
await asyncio.sleep(0)
identity = kwargs.get("identity")
task = kwargs.get("task")
return _make_run_result(identity, task) # type: ignore[arg-type]
Expand Down
11 changes: 9 additions & 2 deletions tests/unit/engine/test_task_engine_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,18 @@ async def slow_save(task: object) -> None:
blocked = asyncio.create_task(
eng.create_task(make_create_data(), requested_by="alice"),
)
await asyncio.sleep(0.05)
# Wait for the engine to enter _process_one and hit slow_save
for _ in range(200):

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.

medium

The polling limit 200 is a magic number. It's also hardcoded in the assertion message on line 62. To improve readability and maintainability, consider defining it as a constant at the start of the test method (e.g., MAX_POLL_YIELDS = 200) and using it in both the loop and in an f-string for the assertion message. This will ensure they stay in sync.

if eng._in_flight is not None:
break
await asyncio.sleep(0)

# The processing loop should be in _process_one with _in_flight set
in_flight_before = eng._in_flight
assert in_flight_before is not None
assert in_flight_before is not None, (
"_in_flight was not set after 200 event-loop yields -- "
"engine did not enter _process_one"
)

# Stop with very short timeout — triggers _fail_remaining_futures
await eng.stop(timeout=0.05)
Expand Down
Loading