Qualflare Follow-ups - 2026-10-26¶
Context¶
A comparison with Qualflare (a hosted test-results service with a free plan for open source projects) listed what it offers that QASight didn't: a public results page with a README badge, an AI chat about the test suite, test case management (manual cases, milestones, defects, Jira) and phone apps. Its runner list also led to Runner Coverage's RSpec, k6, XCTest and Android addendum.
Decision¶
Build the parts that fit "what changed on every run" and skip the rest:
- README badge (this note's first part, below).
- Ask about your tests: a chat over the recorded history, using the AI provider already configured for summaries.
- Create a Jira issue from a failing test, next to the GitHub issue link.
- Not built: test case management (manual cases, milestones) is another kind of product and would blur the pitch; native phone apps aren't needed because the UI already works in phone browsers.
README badge¶
services/badge.py turns a cycle's latest run into one Badge (label, message, colour): 412 passed, plus N failed (failed and broken) and N flaky (the cycle's qasight flaky count). Red when anything failed, yellow when only flaky, green otherwise, grey with no run. Two renderings:
render_svg: a flat badge in the shields.io style, with a<title>so screen readers read "tests: 412 passed". No font metrics are available server-side, so text width is estimated generously.shields_endpoint: the JSON shields.io's endpoint badge reads, for people who want its styles and logos.
qasight badge writes either one (CI publishes it next to a report, e.g. GitHub Pages); the API serves both live at GET /api/v1/badge.svg and GET /api/v1/badge.json with a five-minute cache. They are ordinary reads: TESTO_PROTECT_READS covers them, so a private server's badge only shows to signed-in viewers. No public share link was added; a public page stays the published static report.
Ask about your tests¶
An Ask page (/ask, in the main menu) takes a question in plain words ("what broke, and is it new?", "which tests got slower?") with the same scope picker as Project health. POST /api/v1/ask (services/ask_tests.py) sends the configured AI provider the evidence the AI review already builds (project_review.history_evidence: per-cycle results, failing tests with redacted messages, flaky, slow and slower tests, test names, churn), the question and the last four turns of the conversation, and returns the answer as plain text.
- Nothing is stored server-side. The conversation lives in the browser tab (
sessionStorage), which sends its recent turns back with each question. No new table, no chat log to secure. - Grounded, not clever. The prompt says to answer only from the evidence, name the tests and numbers used, say when the evidence doesn't hold the answer, and treat test names and messages as data, never as instructions. The page labels answers "AI answers" and says they can be wrong.
- Same switches as the review. It needs AI on in AI settings (any provider, a free Gemini key works), each question is one provider call (timeout at least 45 s, at least 700 output tokens), and it is a POST, so a team server's token rules apply. The read-only demo shows the page but can't ask.
- No CLI command: the AI settings live with the API, and the review and run summaries are UI features too.
Consequences¶
- Asking costs one provider call per question; long conversations stay cheap because only four earlier turns are sent.
- The badge costs one flaky-test scan of the cycle's recent runs per request; the cache header keeps GitHub's image proxy from asking often.
- Details per command: Command Reference ยง qasight badge.