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
1 change: 1 addition & 0 deletions .claude/rules/backend/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ pytest は標準 SQLite + `Base.metadata.create_all` で動くため、**本番
- `try / except Exception: pass` をテストコード内で使う(失敗を隠す)
- `time.sleep` での同期待ち(フレーキーになる。`AsyncMock` / `monkeypatch` を使う)
- 過剰モック: SQLAlchemy セッション全体をモックする等。実 DB セッションを使うこと
- **テストで `asyncio.set_event_loop` / `get_event_loop`(グローバル event loop)を触る**: mutmut 3.x は同一プロセスでスイートを複数回実行するため、グローバル loop 状態が実行間に漏れて clean test が `RuntimeError: There is no current event loop` で落ちる(`make mutation-backend` が `Failed to run clean test` で停止した実績)。async は `loop = asyncio.new_event_loop(); try: loop.run_until_complete(...); finally: loop.close()` の分離パターンで実行する(グローバル loop を設定・復元しない)
12 changes: 7 additions & 5 deletions backend/tests/security/test_ssrf_github.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,18 @@


def _run(coro):
"""既存テストの event loop 前提を壊さず非同期関数を実行する。"""
original = asyncio.get_event_loop_policy().get_event_loop()
"""async 関数を専用 event loop で同期実行する(グローバル loop を触らない)。

mutmut 3.x は同一プロセスで pytest スイートを複数回実行するため、
``asyncio.set_event_loop`` / ``get_event_loop`` でグローバル loop 状態に
触れると実行間に汚染が漏れて clean test が落ちる。ローカル loop を作って
閉じるだけの分離パターンにして反復実行に対して冪等にする。
"""
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
return loop.run_until_complete(coro)
finally:
loop.close()
# 一時 loop を閉じたら元の loop へ戻す(新規 loop を作って放置すると leak する)。
asyncio.set_event_loop(original)


@pytest.mark.parametrize("bad", _MALICIOUS_OWNERS)
Expand Down
Loading