Skip to content

Approach

Four habits, written plainly. The links go to public repos where you can see each one in practice.

CI quality gates

A red check blocks the merge, and I test that the gate can actually fail.

A pull request is ready when lint, types, build and tests pass in CI. A failing check blocks the merge; it is not a suggestion to look at later.

A gate that never fails is not a gate. Where I can, I add a negative control: a deliberately broken build that the gate must reject, so the pipeline proves it still bites.

Contract testing

Services agree on their API in a contract, and breaking changes fail in CI, not in staging.

The consumer writes down what it needs from an API, and the provider verifies that contract in its own pipeline. A breaking change shows up as a failed check on the pull request that caused it.

That keeps end-to-end suites small and lets teams deploy independently without guessing.

Accessibility is part of done

axe-core runs with the UI tests, so WCAG regressions fail like any other bug.

Automated checks catch a useful share of accessibility problems early: contrast, names, roles, landmarks. They run next to the functional tests, not in a separate audit once a year.

Keyboard paths and screen-reader names still get checked by hand. This site runs axe on every page in light and dark mode in CI.

A test strategy that fits the risk

Fast checks where they are cheap, a few end-to-end tests where users feel it, and no flaky noise.

Most checks belong at the unit, API and contract level, where they are fast and precise. A smaller set of browser tests covers the flows users actually depend on.

Flaky tests get fixed or quarantined with an owner, not retried until they pass. Risky areas such as payments, messaging and auth get dedicated tests for the failure modes that matter: idempotency, retries, concurrency.

Hiring for QA Lead or SDET?

Let’s talk about your next release.

Based in Kuala Lumpur. Open to relocation and roles abroad with visa sponsorship.