Skip to content
advanced Phase 16 · Capstone Automation Framework

Reporting for Stakeholders

Publish shared dashboards and tailor quality summaries for engineers and leadership.

1h 30m
0 problems
Topic Progress 0%

One URL the Whole Team Reads: Pass Rate, Trend, and Flaky Percentage

The team has test results. What the team needs is one URL that answers, without a single click into a log: is quality improving or decaying? That is the dashboard's whole job — and it is built from five numbers computed the same way on every run.

Publish the report as an artifact of the pipeline, not a folder on someone's disk:

npx playwright test --reporter=json --output-dir=test-results
npx allure generate allure-results --clean -o allure-report
# serve locally while iterating
npx allure open          # http://localhost:5050

In CI, upload allure-report/ as an artifact and mirror it to a gh-pages branch nightly so the stable link — https://acme.github.io/capstone-automation/ — always shows the latest full run. Allure gives you history for free once allure-results are archived between runs, which is the requirement that separates a trend dashboard from a snapshot. Tooling choice is smaller than it looks: Allure plus static hosting is the honest default for a capstone (one container or one branch, no database), while Grafana with a Prometheus data source earns its setup when quality metrics must sit next to service SLOs on one board, and TestOps-style servers add collaboration features at the price of something else to operate.

The five numbers, and the definitions that stop arguments about them:

Metric Formula Healthy Why it exists
Pass rate passed / (total − skipped) ≥ 98% Skipped tests must not inflate it
Flaky rate flaky / total (last 30 runs) < 1% Green-but-untrustworthy visibility
Escape rate prod defects / all defects trending down Does the suite catch what matters?
PR feedback push → verdict, p95 ≤ 15 min Developer trust in the process
Suite duration wall-clock, p50/p95 budget line The cost of every gate decision

Every definition has a way to be gamed, so fix it in the formula. Skip 200 obsolete tests and a raw pass rate jumps while coverage silently fell — exclude skipped. Retry a flaky test twice and the pass rate never moves — count flaky separately and put the percentage on the wall. The one thing that matters: a metric whose formula is not written down will be quoted with three different meanings in the same meeting.

Per-test detail is where the dashboard earns trust with engineers. Allure's Flaky tab lists the offenders with their recent history — checkout-guest-payment failed 7 of its last 30 runs and passed on retry each time. Attach the owner (from a test.info().annotations entry your fixture adds) and the triage command, and the flaky list becomes a work queue instead of a complaint. Annotate trend lines with release markers: the flaky spike at run 4,112 lines up exactly with the merge that introduced parallel worker state in the fixtures, and a graph makes that visible in two seconds while a wall of results never would.

Keep the dashboard honest by making it fully automated: generated in the pipeline, published on schedule, containing no manually pasted numbers. The moment someone edits a figure before a review, the URL stops being trusted and email attachments come back. The teams that get this right stop arguing about whether quality is fine and start arguing about which panel to fix first — a much better argument to be having. Your dashboard is for the team's daily reading; the next piece splits the same underlying data into what each stakeholder group actually needs.

Same Data, Three Emails: What Engineers, Managers, and Leadership Each Need

Every quality report you have ever read badly was the same report sent to everyone: wall-of-text test names for a VP, "coverage went up" for an engineer who needed the failing diff. The capstone's reporting is one dataset rendered three ways, because the audience's question defines the report, not the data you happen to have.

Engineer Manager Leadership
Question What broke, and how do I reproduce it? What is at risk this sprint? Can we ship, and is quality improving?
Horizon This run Last 2 weeks Last 2–4 releases
Metrics Failing test, trace link, diff, owner Flaky %, PR feedback p95, blocked PRs, open quarantine tickets Escape rate, trend, critical-journey coverage
Format Pipeline annotation, Slack thread One screen, weekly ≤ 5 bullets, monthly
Channel CI + #eng-quality #qa-capstone Email / review deck

The engineer view is generated by the pipeline, not written by a human. A failing smoke test posts the test title, the shard, a link to the trace artifact, and a copy-paste reproduction:

npx playwright test checkout --grep "guest pays with card" --headed
npx playwright show-trace test-results/checkout/trace.zip

The manager view is the dashboard from Wiring the Capstone into CI plus a weekly digest that reports movement, not levels: flaky 1.4% → 0.8% after the fixture rewrite; PR feedback p95 at 12:40 against the 15-minute budget; 3 tests in quarantine, oldest ticket QAI-1183 at 9 days. Leadership gets the trend in the language of risk: escape rate 8%, down from 15% two quarters ago; the two production incidents this quarter both mapped to the payment-redirect journey, where a new contract test now runs; no open release blockers.

Two rules keep the three renderings consistent. First, one source of truth: every view derives from the same pipeline artifacts and metric definitions, so no audience can be shown 98% while another is shown 96%. When two numbers in one meeting disagree, trust in all reporting dies at once. Second, the weekly and release-readiness digests are generated, never compiled by hand:

- name: Release readiness
  if: github.event_name == 'schedule'
  run: node scripts/report/release-readiness.js   # posts to Slack webhook
  env:
    SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
    BASELINE_ESCAPE_RATE: 0.15   # quarter's starting point

The script reads the JUnit XML from the nightly run, joins escape-rate history from a small JSON store, and posts a fixed template — pass rate, flaky rate, duration, top 3 offenders with owners, quarantine count, escape-rate delta. It runs in about 40 seconds, and nobody ever assembles the update manually, which is the only reason it keeps being sent in week 30.

The template is short on purpose — five lines plus links, because a digest that needs a meeting to parse stops being read. Every number carries its comparison (flaky 0.8%, ↓ 0.6 pts) and every red item carries an owner and a due date. When a metric crosses a threshold, the script appends the relevant dashboard panel link, so the digest points at the evidence rather than replacing it — the digest is the index, the dashboard is the record, and the trace is the truth.

The skill interviewers are testing with "how do you communicate quality to non-technical stakeholders?" is translation with discipline: lead with risk and trend, in bullets, with a date and an owner on anything actionable — and keep the trace links available for the one engineer in the room who asks. The third audience-facing move is the one nobody plans for: when something does escape, the report has to explain why, which is the root-cause work in the next chapter.

Escaped Defects and Root Cause: Turning Production Bugs Into Suite Changes

A production incident is filed: customers report their coupon applied twice and orders were discounted 40%. The framework had 1,840 passing tests. The question that determines whether this repeats is not "who missed it" but which layer of the defense was absent — and the answer is recorded, not debated.

Start with a metric that can be argued about precisely. Define escape rate once and put the formula in the dashboard:

escape rate = defects found in production / (defects in production + defects caught pre-release)

this quarter:  4 / (4  + 46)  = 8%
last quarter:  9 / (9  + 51)  = 15%

An 8% that fell from 15% tells a story the raw bug count never could. Pair it with a severity split — a P1 escape and a cosmetic escape are not the same defense failure — and with "escapes per release" so a quarter with two hotfixes cannot hide behind a big release batch.

Then classify. Every escape gets a root-cause category at a 30-minute blameless review, and each category has a prescribed suite action:

Root cause What was missing Suite action
No test case Scenario never imagined Add the test at the cheapest layer that proves it
Test existed, was wrong Assertion too weak Strengthen assertion; re-check siblings
Flaky masked it Failures normalized away Fix stability first, then re-run 30×
Environment parity Staging lacks the config Add a staging config-diff check
Requirement gap Nobody knew the rule Update the charter; session-based follow-up

Walk the double-coupon case through the table. Five whys: the coupon doubled → the API allowed stacking → POST /coupons/apply had no idempotency or uniqueness constraint test → the contract suite covered status codes and schemas, not business rules → business rules lived only in UI tests, where the tester assumed the API checked them. The class is no test case at the API layer, and the action is concrete:

test('applying the same coupon twice returns 409 @contract', async ({ api, customer }) => {
  await api.applyCoupon(customer, 'SAVE40');
  const res = await api.applyCoupon(customer, 'SAVE40');
  expect(res.status()).toBe(409);
  expect((await api.getOrder(customer)).discount).toBe(40);   // not 80
});

That test is committed with the incident ID in its body, and the process fix — business-rule cases must exist at the API layer before a journey is called covered — goes into the review's second output. One test plus one process change per escape is the ritual; either alone is the same incident wearing a calendar costume.

The release-readiness report closes the loop, because prevention has to arrive before the release, not after it:

node scripts/report/release-readiness.js --tag v4.2.0
# → pass rate 98.6% · flaky 0.7% · quarantine 3 · blockers 0
# → escape trend 15% → 11% → 8% · readiness: GO with notes

Automated from the nightly artifacts, posted to the release channel the morning of a deploy decision — the same pipeline data as the dashboards and digests, rendered for the one meeting where quality is decided. When an escape still happens, the review has made the response mechanical instead of political: classify, add the test, change the rule, update the trend. That is also the raw material for the final chapter, where the framework's own future gets reviewed and demonstrated in Maintenance, Review, and Demo.

Quiz

1. Two hundred obsolete tests are marked skip. How must the dashboard's pass-rate formula guard against the resulting illusion?

Question 1 options

2. A test fails once and passes on retry in 7 of its last 30 runs. What does a trustworthy dashboard show?

Question 2 options

3. Leadership asks for a quality update. Which rendering is correct?

Question 3 options

4. A coupon applied twice in production; only UI tests covered the rule and the API accepted the repeat. Which root-cause class and action apply?

Question 4 options

Flashcards

Question

The five dashboard metrics, their formulas, and what each formula prevents.

Answer

Pass rate = passed/(total − skipped) · Flaky rate = flaky/total over the last 30 runs · Escape rate = prod defects/(prod + pre-release defects) · PR feedback p95 (push → verdict) · Suite duration p50/p95. Each formula closes a specific loophole: skipped tests, retries, batch-size distortions.

Question

Why must all three audience reports derive from one dataset?

Answer

Engineers, managers, and leadership get different renderings (repro command + trace link / one-screen sprint risk / ≤5 bullets of trend), but if two views quote different numbers in one meeting, trust in all reporting dies at once. One source of truth, three renderings, identical formulas.

Question

What are the mandatory outputs of an escaped-defect review?

Answer

From a 30-minute blameless session: one committed test at the cheapest layer that could have caught the bug (referencing the incident ID) and one process change (e.g., business rules must have API-layer cases before a journey counts as covered). Either output alone is the same incident rescheduled.

Question

What makes a release-readiness report trustworthy rather than theater?

Answer

It is generated by script from nightly pipeline artifacts (~40 seconds), posts itself to the release channel, contains zero manually pasted numbers, and states readiness as GO/NO-GO with notes plus the escape-rate trend — nobody ever compiles it by hand, which is why it keeps getting sent.

Question

Why annotate dashboard trend lines with release markers?

Answer

Correlation becomes visible in two seconds — a flaky spike lining up with the merge that introduced parallel worker state in the fixtures explains itself on a graph, while the identical fact stays invisible inside a wall of per-run results.

Revision Notes

Key Takeaways

  • 1. A dashboard is one URL that answers 'improving or decaying' — snapshots without archived history cannot show trend, and trend is the actual question
  • 2. Every metric needs a written formula because every metric has a way to be gamed; skipped tests, retries, and release batching are the classic distortions
  • 3. One dataset, three renderings: lead with the audience's question and horizon, and keep the digest five lines plus links
  • 4. Escaped defects are classified, not debated — each one produces a test and a process change, and the escape-rate trend is the scoreboard
  • 5. Reporting that is generated never lapses: dashboards, digests, and readiness posts all derive from pipeline artifacts with no manual step

Interview Tips

  • • "How do you report quality?" — one dashboard with written formulas, audience-specific renderings of one dataset, and automation from pipeline artifacts; mention flaky-visible-on-green as the trust detail
  • • "How would you communicate quality to non-technical stakeholders?" — risk and trend first, bullets with owners and dates, no test counts; state the five-bullet limit for leadership
  • • "What is escape rate and what do you do with it?" — prod/(prod+pre-release) with severity split; classify at a blameless review into one of five categories, then one test plus one process change
  • • "A metric moved — how do you know it is real?" — check the formula's loophole first (skips, retries, batching), then correlate with release markers on the trend line before telling any story

Cheat Sheet

Reporting for Stakeholders

Publishing: npx allure generate allure-results --clean in CI → artifact + gh-pages mirror; archive allure-results between runs so history (trends) exists. Stable URL = the dashboard.

Metric formulas (write them down or they get quoted three ways):

Metric Formula Healthy
Pass rate passed / (total − skipped) ≥ 98%
Flaky rate flaky / total, last 30 runs < 1%
Escape rate prod / (prod + pre-release) trending down
PR feedback push → verdict, p95 ≤ 15 min
Duration wall-clock p50/p95 budget line

Audience matrix: engineer = this run, repro command + trace · manager = 2 weeks, one screen, weekly · leadership = 2–4 releases, ≤5 bullets, monthly. Same dataset, no per-audience recomputation.

Escape review ritual (30 min, blameless): classify → one test at the cheapest adequate layer + one process change → update the trend. Categories: no test case · weak assertion · flaky masked · env parity · requirement gap.

Automation: nightly script reads JUnit XML, joins history, posts the digest/readiness (GO/NO-GO) to Slack in ~40s. Digits are never pasted by hand.

Continue Learning