test(perf): add Lighthouse benchmark suite and CI job#6494
Conversation
Adds a Playwright-driven Lighthouse benchmark for integration tests, a runner script, fixtures and helpers, plus a CI job that uploads the generated report so frontend performance regressions are caught.
Merging this PR will not alter performance
Comparing Footnotes
|
Greptile SummaryThis PR introduces a Playwright-driven Lighthouse benchmark suite for Reflex production apps, including shared utilities, a CI job, integration and unit tests, and a local runner script. The benchmark builds a real landing-page Reflex app in prod mode, warms up the server, and audits performance/accessibility/best-practices/SEO with a 90-point threshold for each category.
Confidence Score: 3/5The benchmark infrastructure is well-structured overall, but the warmup failure path calls proc.wait(timeout=10) without catching subprocess.TimeoutExpired, which will discard the diagnostic message and leave the subprocess un-killed. The warmup failure branch in _run_prod_lighthouse_benchmark silently swallows the pytest.fail() call whenever the reflex subprocess does not exit within 10 s — a realistic scenario under CI load. Every other proc.wait(timeout=10) call in the same function correctly wraps the call in try/except and follows it with proc.kill(), so the omission stands out and will produce misleading failures. tests/integration/lighthouse_utils.py — specifically the else branch of the warmup loop around line 1128 Important Files Changed
Sequence DiagramsequenceDiagram
participant CI as GitHub Actions
participant pytest as pytest runner
participant utils as lighthouse_utils
participant reflex as reflex run --env prod
participant lh as Lighthouse CLI
CI->>pytest: uv run pytest test_lighthouse.py
pytest->>utils: run_landing_prod_lighthouse_benchmark()
utils->>utils: _ensure_lighthouse_app() scaffold app + copy fixtures
utils->>reflex: subprocess.Popen(reflex run --env prod --frontend-only)
loop read stdout until URL found or deadline
reflex-->>utils: App running at: http://0.0.0.0:3001
end
utils->>utils: _get_lighthouse_target_url() rewrite 0.0.0.0 to 127.0.0.1
loop warmup until server responds or 30 s
utils->>reflex: urllib.request.urlopen(http://127.0.0.1:3001)
end
utils->>utils: get_lighthouse_command() + get_chrome_path()
utils->>lh: "subprocess.run(lighthouse http://127.0.0.1:3001 --output=json ...)"
lh-->>utils: landing-prod-lighthouse.json
utils->>reflex: proc.terminate() + proc.wait()
utils-->>pytest: LighthouseBenchmarkResult(report, summary, failures)
pytest->>CI: upload artifact lighthouse-report/
|
Detect chrome-headless-shell and skip the --headless=new flag it rejects, route the scratch dir through reflex_base constants, exclude the *current symlinks from the uploaded artifact, and temporarily lower the performance threshold to 0.56 while we tune the CI baseline.
Revert the headless-shell detection now that the runner ships full Chrome, and remove the unused app_name parameter from _run_prod_lighthouse_benchmark.
Adds a Playwright-driven Lighthouse benchmark for integration tests, a runner script, fixtures and helpers, plus a CI job that uploads the generated report so frontend performance regressions are caught.
All Submissions:
Type of change
Please delete options that are not relevant.
New Feature Submission:
Changes To Core Features: