Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

Testing & Quality

Testing isn't optional — it's how you prove you care.

Quality here isn't a checklist. It's a design force — every layer of the stack has a gate, every gate has teeth, and nothing reaches production without proving it belongs there.

First Principles

  • A gate is binary — pass or fail, never "mostly acceptable"
  • Gates have teeth — a warning is not a gate; exit code 1 is
  • Gates belong in the feedback loop — pre-push or CI, not PR review
  • Coverage is a floor, not a ceiling — mutation score proves the tests mean something
  • Property tests find what unit tests assumed away
  • Measure at natural granularity — per-method, per-type, per-namespace; never global averages that mask local debt
  • Self-hosted — QualityGate gates itself: 256 tests, 100% line/branch coverage, mutation score 1.0

Test-Driven Design

  • TDD — tests drive design, not just verify it
  • No mocking frameworks — FakeHttpClient, hand-written fakes, deterministic tests
  • Mutation testing (Stryker) — test quality score >= 0.95
  • 100% code coverage as design pressure, not a vanity metric
  • Property-based testing (fast-check) for fuzzy invariants

Professional Testing at Scale

  • Revived ~800 unit tests at BIM&CO — built a multi-threaded execution framework with async lambda encapsulation, cutting test suite from non-functional to running in ~20 minutes
  • Aspire testing layer — mini framework on top of .NET Aspire to reduce test boilerplate (BIM&CO)
  • CucumberJS E2E — set up the npm/TypeScript + CucumberJS test stack with Selenium infrastructure (Qwant)
  • Selenium — E2E testing coordination across multiple projects (Qwant, AUSY)

Code Quality as Static Analysis

Not opinions — metrics. QualityGate runs Roslyn-powered analysis on every build: cyclomatic complexity, cognitive complexity, afferent/efferent coupling (Ca/Ce), cohesion (LCOM4), maintainability index. Thresholds live in quality-gate.yml, enforced in CI with pass/fail exit codes. The build doesn't warn — it fails.

Visual Quality as Baselines

Every page is screenshotted across 4 themes (dark, light, dark-hc, light-hc) and multiple viewports. Baselines are checked in. When a pixel changes, the diff is visible and intentional — or the test fails.

New pages get auto-generated baselines on first run. A smoke mode tests a curated set of stable pages on every push, so content additions don't break the suite. Full regression runs on demand.

Accessibility as a Gate, Not an Afterthought

axe audits on every page, accent color contrast matrix testing, ARIA role verification, keyboard-first navigation, screen-reader announcements. Accessibility isn't a separate pass — it's woven into the same test pipeline that checks rendering.

Requirements as Compile-Time Proof

Features are abstract classes with acceptance criteria as abstract methods. Tests link to features via typed decorators. A compliance scanner verifies 100% AC coverage — if an acceptance criterion has no test, the build knows.

The Gate Before Push

Husky pre-push hook: unit tests + smoke Playwright + compliance scan. All three must pass before git push succeeds. No bypassing, no --no-verify. If the gate fails, the code stays local until it's fixed.

C# Quality Gates

Gate Tool Metric Threshold
Complexity QualityGate (Roslyn) Cyclomatic / cognitive per method ≤ 15 / ≤ 20
Cohesion QualityGate (Roslyn) LCOM4 per type ≤ 25
Coupling QualityGate (Roslyn) Efferent coupling per type ≤ 70
Maintainability QualityGate (Roslyn) Maintainability index per method ≥ 55
Architecture QualityGate (Roslyn) Distance from main sequence per namespace ≤ 1.0
Coverage XPlat Code Coverage (coverlet) Line + branch 100%
Mutation Stryker.NET Mutation score ≥ 0.95
Property testing CsCheck Randomized invariants 0 counterexamples
CI gate quality-gate check All gates above exit 0

TypeScript Quality Gates

Gate Tool Metric Threshold
Type safety TypeScript strict Type errors 0
Lint ESLint Violations 0
Coverage Istanbul / nyc Line + branch 100%
Mutation Stryker (stryker-mutator) Mutation score ≥ 0.90
Property testing fast-check Randomized invariants 0 counterexamples
Visual regression Playwright Pixel diff vs baseline 0
Accessibility axe-core Violations 0
Pre-push gate Husky All gates above blocked on failure
⬇ Download