DevOps QA / Intermediate: trustworthy validation systems / Lesson 11
Accessibility and performance gates
Introduce nonfunctional checks with meaningful scope, stable measurement, and honest treatment of what automation cannot establish.
On this page
Lesson goals
- Combine automated accessibility checks with task-based review.
- Evaluate performance against a controlled baseline and user requirement.
Specify the task and population
Accessibility and performance are properties of user journeys under conditions, not generic badges attached to an application. Name a booking task, supported assistive technologies, relevant device and network classes, and acceptable responsiveness. Automated checks can detect important classes of issues but cover only what the tool and scenario exercise. A fast empty page or a scan of a closed dialog says little about completing a real reservation. Choose representative states such as validation errors, loading, confirmation, and narrow layouts, then connect each gate to an explicit requirement and owner.
Scan a meaningful state and review the journey
Axe integration with Playwright can check a rendered state after the UI reaches the intended condition. Scope exclusions carefully and keep a reason and expiry for any accepted violation. Automated accessibility scans do not establish complete WCAG conformance or the usability of keyboard and screen-reader navigation. Add task traversal, focus order, error association, and manual review where needed. The example uses a synthetic local booking form and a pinned compatible axe integration. It performs no scan until a configured test environment is actually run outside this course.
import { test, expect } from "@playwright/test";
import AxeBuilder from "@axe-core/playwright";
test("booking form has no detected accessibility violations", async ({ page }) => {
await page.goto("/workshops/owned-workshop");
await expect(page.getByRole("button", { name: "Reserve" })).toBeVisible();
const result = await new AxeBuilder({ page }).analyze();
expect(result.violations).toEqual([]);
});
Requires local baseURL, synthetic fixtures, matching browser binaries, and compatible pinned Playwright/axe packages. The test title says detected violations rather than claiming the whole application is accessible. Add checks for the error and confirmation states separately.
Control performance measurement inputs
Performance results depend on workload shape, data size, warmup, runtime, runner contention, cache state, and instrumentation. Record them before comparing candidates. A shared CI runner may be appropriate for a coarse smoke budget but too noisy for a small regression threshold. Keep correctness assertions alongside latency because an endpoint can become faster by returning an error. Use repeated bounded measurements in an authorized isolated environment; this course does not send load. Treat insufficient samples or incomparable environments as inconclusive rather than choosing whichever run makes the candidate pass.
Use absolute budgets and relative comparison
An absolute budget protects a user requirement, while a relative baseline comparison detects change within a controlled setup. They complement one another: a baseline can already be unacceptably slow, and a small relative difference can be noise. The function below summarizes repeated synthetic run-level measurements with a median and applies a clearly labeled teaching threshold. It is not a statistical significance test or a method for combining request percentiles. Production decisions require sample adequacy, uncertainty, baseline provenance, and workload comparability. Keep baseline changes reviewable so failures are not erased by automatic replacement.
from statistics import median
def perf_review(baseline_runs, candidate_runs):
if len(baseline_runs) < 5 or len(candidate_runs) < 5:
return "inconclusive"
base = median(baseline_runs)
current = median(candidate_runs)
if base <= 0:
return "invalid baseline"
return "review regression" if current > base * 1.10 else "within teaching budget"
Inputs are comparable run-level durations in the same units. Five runs and ten percent are illustrative choices, not universal statistical guarantees. A real gate also checks an absolute user budget and environment metadata and reports uncertainty.
Mature the signal before enforcing it
Introduce a new check visibly in advisory mode while evaluating stability, diagnostic value, and ownership. Define promotion criteria for enforcement and ensure serious user-impacting findings still receive review during that period. Performance thresholds in tools such as k6 determine pass/fail for configured metrics; ordinary checks and thresholds have different semantics. Verify the tool version and output behavior before wiring a gate. Preserve raw bounded measurements, scenario identity, and baseline history. Review manual accessibility findings and automated results together so a green scan never becomes permission to ignore a broken user task.
Common errors and fixes
A green scan is reported as complete accessibility
- Why it happens
- Tool scope is mistaken for the whole user experience.
- How to fix it
- Add task-based keyboard and assistive-technology review.
- Prevent it next time
- State automated coverage and limitations explicitly.
Small performance changes block randomly
- Why it happens
- Noise exceeds the chosen threshold.
- How to fix it
- Control the environment and establish uncertainty before enforcement.
- Prevent it next time
- Validate baseline quality and sample adequacy.
A faster failure response passes the gate
- Why it happens
- Only latency is measured.
- How to fix it
- Require successful business outcomes and error budgets.
- Prevent it next time
- Keep correctness and performance evidence connected.
Check your understanding
1. A candidate is 3% slower on a runner varying 12% between equivalent runs. Decide the gate result.
Show worked solution
The comparison is inconclusive at that precision. Investigate contention and improve measurement conditions or use a broader justified smoke threshold. Preserve the observation without declaring either a confirmed regression or a clean performance pass.
2. Axe finds no issues, but keyboard users cannot close the booking dialog. What should block?
Show worked solution
The broken user task remains an accessibility defect under the feature requirement. Add a focused interaction test and manual verification, repair focus and dismissal behavior, and do not use the automated scan as a waiver.
Key takeaways
- Nonfunctional gates need task scope and trustworthy measurement.
- Noisy evidence should become inconclusive, not convenient certainty.
- Automated scans complement user-task verification.