Improve tailoring and job fetch resilience

This commit is contained in:
2026-08-03 00:57:19 +03:30
parent 81d816ae54
commit 50cc879e1e
6 changed files with 311 additions and 19 deletions
+41
View File
@@ -123,6 +123,47 @@ def test_tailor_runs_draft_and_audit() -> None:
assert result == expected
def test_tailor_restores_canonical_contact_after_each_model_pass() -> None:
draft = package()
audited = package()
for result in (draft, audited):
result.resume.contact = ContactInfo(
full_name="Reformatted Name",
email="changed@example.com",
phone="000",
location="Changed location",
linkedin="https://example.com/changed",
website=None,
)
result = tailor_resume(FakeLLM([draft, audited]), profile(), "long job post")
assert result.resume.contact == CONTACT
def test_revision_restores_canonical_contact_after_each_model_pass() -> None:
revised = package()
audited = package()
for result in (revised, audited):
result.resume.contact = ContactInfo(
full_name="Reformatted Name",
email="changed@example.com",
phone=None,
location="London",
linkedin=None,
website=None,
)
result = revise_tailored_resume(
FakeLLM([revised, audited]),
profile(),
package(),
"Make the summary more direct.",
)
assert result.resume.contact == CONTACT
def test_tailoring_strength_controls_rewriting_without_relaxing_evidence() -> None:
expected = package()
llm = FakeLLM([expected, expected])
+108
View File
@@ -0,0 +1,108 @@
from __future__ import annotations
from typing import Any
import httpx
import pytest
from resume_agent import web
def _mock_client(
monkeypatch: pytest.MonkeyPatch,
handler: Any,
captured: dict[str, Any] | None = None,
) -> None:
original_client = httpx.Client
transport = httpx.MockTransport(handler)
def client_factory(**kwargs: Any) -> httpx.Client:
if captured is not None:
captured.update(kwargs)
return original_client(transport=transport, **kwargs)
monkeypatch.setattr(web.httpx, "Client", client_factory)
monkeypatch.setattr(web, "_validate_public_url", lambda _url: None)
def test_job_fetch_retries_transient_connection_timeout(
monkeypatch: pytest.MonkeyPatch,
) -> None:
attempts = 0
def handler(request: httpx.Request) -> httpx.Response:
nonlocal attempts
attempts += 1
if attempts == 1:
raise httpx.ConnectTimeout("timed out", request=request)
return httpx.Response(
200,
headers={"content-type": "text/html; charset=utf-8"},
text="<html><body><h1>Backend Engineer</h1></body></html>",
)
_mock_client(monkeypatch, handler)
result = web.fetch_job_page(
"https://jobs.example/role",
timeout_seconds=120,
retries=1,
retry_backoff_seconds=0,
)
assert result == "Backend Engineer"
assert attempts == 2
def test_job_fetch_reports_timeout_as_job_page_error(
monkeypatch: pytest.MonkeyPatch,
) -> None:
attempts = 0
def handler(request: httpx.Request) -> httpx.Response:
nonlocal attempts
attempts += 1
raise httpx.ConnectTimeout("timed out", request=request)
_mock_client(monkeypatch, handler)
with pytest.raises(web.JobPageError, match="after 3 attempts"):
web.fetch_job_page(
"https://jobs.example/role",
timeout_seconds=120,
retries=2,
retry_backoff_seconds=0,
)
assert attempts == 3
def test_job_fetch_timeout_is_configurable(
monkeypatch: pytest.MonkeyPatch,
) -> None:
captured: dict[str, Any] = {}
def handler(_request: httpx.Request) -> httpx.Response:
return httpx.Response(
200,
headers={"content-type": "text/plain"},
text="Complete job description",
)
_mock_client(monkeypatch, handler, captured)
monkeypatch.setenv("RESUME_AGENT_JOB_FETCH_TIMEOUT_SECONDS", "240")
monkeypatch.setenv("RESUME_AGENT_JOB_FETCH_RETRIES", "0")
assert web.fetch_job_page("https://jobs.example/role") == "Complete job description"
timeout = captured["timeout"]
assert timeout.connect == 60
assert timeout.read == 240
def test_job_fetch_rejects_invalid_timeout_configuration(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv("RESUME_AGENT_JOB_FETCH_TIMEOUT_SECONDS", "not-a-number")
with pytest.raises(web.JobPageError, match="must be a number"):
web.fetch_job_page("https://jobs.example/role")