Skip to content

QA / Test Engineer

Find risk before users do and turn quality into something the team can measure

A path from testing mindset and test design techniques, through API testing and Playwright automation, to non-functional testing, quality engineering and AI in testing. For manual testers moving into automation or SDET work, and for developers who want to take the QA craft seriously.

Start at stage 01
stages
10stages
topics
50topics
weeks, part-time
~36weeks, part-time
  • Foundation
  • Core
  • Advanced
  • PlaywrightPlaywright
  • TypeScriptTypeScript
  • Bruno
  • Pact
  • k6
  • axe-core
  • Appium
  • Maestro

My take

I am a frontend developer, not a QA specialist. Over the years I have worked closely with testers, read their bug reports every day, and written Playwright tests for the critical flows of the apps I build. That is when I realized that writing a test that goes green is very different from knowing what to test. This map collects what I learned from my QA teammates and from digging in myself, plus the path I would follow if I started as a QA engineer or SDET today.

What I wish I had known earlier

  • Tools change every few years, while test design techniques like equivalence partitioning and boundary values last a career, so learn them before any framework.
  • A flaky test is worse than no test, because it teaches the team to ignore red. I wish I had treated flakiness as a real bug much earlier.
  • A good bug report is one a developer can reproduce after reading it once. Steps, expected result and evidence matter more than a long description.
  • Automation does not replace exploratory testing. Scripts only check what we already thought of, while a good tester finds what nobody thought of yet.
0 of 10 stages passed

Foundation01–03

  1. 01Stage 01, 2 weeksTesting mindset and test levelsExplain why and at which level a feature should be tested, based on risk rather than gut feeling.
    Early on I thought testing was about proving the code works. My QA teammates taught me that the real goal is to surface information about risk, including information nobody wants to hear.

    What to learn

    Test levels
    Unit, integration, component, end-to-end and acceptance tests differ in scope, speed and maintenance cost. Understanding the boundaries helps you place each check at the cheapest level that still catches the bug. Also separate verification (built to spec) from validation (built what users need).
    Test pyramid vs testing trophy
    Mike Cohn's pyramid recommends many unit tests and few E2E tests. Kent C. Dodds' testing trophy puts the weight on integration tests because they give the most confidence per unit of cost. Both are heuristics, not laws: the right shape depends on your architecture and where real bugs tend to appear.
    Risk-based testing
    Rate each risk by likelihood times impact and spend testing effort accordingly. Payments, permissions and user data deserve deeper coverage than the about page. A simple risk matrix also lets you defend a decision not to test something deeply.
    Shift-left and QA in agile
    Shift-left means QA joins at story refinement: questioning acceptance criteria, edge cases and testability before any code exists. Three amigos sessions (product, dev, QA) and Given/When/Then acceptance criteria surface misunderstandings early. Modern QA leads quality for the whole team instead of acting as a gate at the end of the sprint.
    The seven testing principles
    The ISTQB CTFL v4.0 syllabus sums up principles such as testing shows the presence of defects, not their absence, exhaustive testing is impossible, and defects cluster together. They sound obvious but give you solid ground when someone asks why not everything was tested.

    Do

    • Read acceptance criteria and write down edge-case questions before implementation or testing starts.
    • Tie every test to a specific risk so you know why it exists.
    • Pick the lowest test level that still catches the kind of bug you worry about.
    • Record what you decided not to test and why.

    Watch out for

    • Measuring quality by the number of test cases instead of the risk reduced.
    • Treating QA as the last phase of the sprint, handing testers a build when it is too late to change the design.

    Checkpoint project: Risk map for a real feature

    Pick a feature such as sign-up or the cart in an app you use daily, list at least 10 risks and score likelihood and impact. It passes when every risk has a suggested test level (unit, integration, E2E, manual) with a one-sentence justification.

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4StarterA pure function calculates VAT and rounding for an order total. Where should most of its rounding edge cases be checked?
    2. Question 2 of 4StarterA manager asks why 2,000 passing tests did not prove the release was bug-free. Which testing principle answers this?
    3. Question 3 of 4StarterYou have two days to test a release touching the payment flow, the about page and avatar upload. How should risk-based testing split your effort?
    4. Question 4 of 4StarterIn story refinement, a story says 'User can apply a discount code'. What is the most valuable shift-left action for QA?
  2. 02Stage 02, 3 weeksTest design and exploratory testingDesign a lean set of test cases with strong risk coverage, run chartered exploratory sessions and write bug reports developers can reproduce immediately.
    This is the stage developers skip most, me included. The first time I watched a QA teammate apply boundary values to a form, I understood why they found bugs so fast.

    What to learn

    Equivalence partitioning and boundary values
    Equivalence partitioning groups inputs the system treats the same, so one representative per group is enough. Boundary value analysis tests at and around the edges, for example ages 17, 18, 65 and 66 for a range of 18 to 65. Do not forget invalid partitions such as empty strings, negative numbers, Unicode and overly long values.
    Decision tables and pairwise
    A decision table lists combinations of conditions and the resulting actions, ideal for discount rules or permission logic with many branches. When combinations explode, pairwise testing picks a subset that covers every pair of values, cutting case count sharply while still catching most two-parameter interaction bugs.
    State transition testing
    Draw a state diagram for objects with a lifecycle, such as an order (draft, paid, shipped, cancelled), then test both valid and invalid transitions. Bugs often hide in forbidden transitions the system still allows, like cancelling a delivered order or paying twice.
    Exploratory testing with charters
    Exploratory testing is simultaneous learning, test design and execution, structured rather than random clicking. A charter in Elisabeth Hendrickson's template reads: explore area X, with resources Y, to discover information Z. Session-based test management timeboxes each session to 60 to 90 minutes and ends with notes, bugs and open questions.
    Bug reports developers want to read
    A good bug report has a title naming symptom and location, minimal reproduction steps, actual versus expected result, environment (browser, build, test account) and evidence such as a screenshot, video, HAR or trace ID. Keep severity (technical impact) separate from priority (business order). One bug per report.

    Do

    • For every input field, list valid partitions, invalid partitions and boundary values before writing cases.
    • Write a charter before each exploratory session and take notes during it, not afterwards.
    • Reduce reproduction steps to the minimum before filing a bug.
    • Attach verifiable evidence such as a video, HAR file or request ID.

    Watch out for

    • Writing hundreds of near-identical test cases instead of applying equivalence partitioning.
    • Filing a bug that only says 'does not work' with no environment or expected result.

    Checkpoint project: Test suite for a booking form

    Using a public demo like Restful Booker, design test cases with equivalence partitioning, boundary values and a decision table for pricing rules. Run two chartered exploratory sessions and file at least three bug reports using the template, each reproducible in five steps or fewer.

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4StarterAn age field accepts 18 to 65 inclusive. Which set of values applies boundary value analysis correctly?
    2. Question 2 of 4StarterWhy does pairwise testing cut the number of cases sharply while still catching most configuration bugs?
    3. Question 3 of 4StarterAn order moves draft, paid, shipped, delivered, and can be cancelled only before shipping. Which test is most likely to reveal a hidden bug?
    4. Question 4 of 4StarterWhich bug report title is most useful for the developer who picks it up?
  3. 03Stage 03, 2 weeksWeb, HTTP and DevTools for testersRead requests, responses, cookies and the console to narrow a bug down to the frontend, the API or the infrastructure.
    From the frontend side, the most valuable bug reports I received always came from testers who opened the Network tab. Just a status code and a response body cut debugging time dramatically.

    What to learn

    HTTP basics
    Know methods (GET, POST, PUT, PATCH, DELETE), idempotency, status code families 2xx, 3xx, 4xx, 5xx and common headers like Content-Type, Authorization and Cache-Control. Telling 401 from 403 and 404 from 410 points the bug at the right place.
    Cookies, sessions, tokens and CORS
    Understand HttpOnly, Secure and SameSite cookies, the difference between session cookies and JWTs, and why a CORS error shows up in the browser while the same call works in an API client. Many login, session-expiry and permission bugs hide here.
    Chrome DevTools for testing
    Use the Network tab to filter requests, inspect payloads, throttle the network and export a HAR. The Application tab shows storage, cookies and service workers. The Console catches JavaScript errors, while Device Mode and Rendering emulate viewports, prefers-color-scheme and reduced motion.
    Rendering and async state
    Modern apps render on the client and data arrives later, so there are loading, empty, error and stale states. Knowing how browser cache, CDNs and libraries like TanStack Query behave helps you explain the classic 'it goes away after refresh' bug.

    Do

    • Keep DevTools open in every test session with Preserve log enabled in the Network tab.
    • Attach status code, request ID and response body to every API-related bug.
    • Re-test every critical flow on a slow network and when the API returns errors.

    Watch out for

    • Reporting a UI bug when the real cause is an API returning 500.
    • Ignoring red errors in the Console because the screen looks fine.

    Checkpoint project: Request map of a user flow

    Take the login then add-to-cart flow of a demo app, record every request as a HAR and diagram who calls what and what comes back. It passes when you can point to the cookie or token that holds the session and describe what happens when the cart API fails.

    • HTTP
    • DevTools
    • Debugging

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4StarterA logged-in user opens an admin page and the API returns 403. What does that tell you?
    2. Question 2 of 4StarterAn API call works in Postman but fails in the browser with a CORS error. Why?
    3. Question 3 of 4StarterA list page shows 'No items yet' for a user who has items. In the Network tab the list request returns 500. How should you file it?
    4. Question 4 of 4StarterWhy is automatically retrying a PUT usually safer than retrying a POST?

Core04–08

  1. 04Stage 04, 4 weeksProgramming for testers with TypeScriptWrite clean test code in TypeScript: functions, async/await, modules, types and a test runner.
    Many testers I know jumped straight into an automation framework, skipped the language and got stuck on async/await. If your team uses Python, go with Python; what matters is knowing one language well.

    What to learn

    Choosing a language: TypeScript or Python
    TypeScript pairs with Playwright, k6 and most frontends, so you can read your developers' code. Python shines with pytest, data work and AI tooling. Follow your team's stack, since tests should live in the same repo and language as the product when possible.
    Async, promises and async bugs
    Almost every UI and API action in automation is asynchronous. Understanding promises, async/await, Promise.all and what happens when you forget an await (false passes or detached errors) is a survival skill.
    Types and structuring test code
    Typing test data and responses catches mistakes before the run. Learn to extract helpers, data builders and modules, but keep tests readable with Arrange, Act, Assert. Test code is QA's production code and deserves the same review and refactoring.
    Test runners and assertions
    Get comfortable with a unit test runner like Vitest or pytest to understand describe blocks, hooks, assertions, mocks and snapshots. Reading developers' unit tests also tells you what is already covered so you do not duplicate it at the E2E level.
    Git and review workflow
    Branches, small commits, pull requests and resolving conflicts are daily SDET work. Reading a developer's diff helps you predict which areas just became risky and focus your testing there.

    Do

    • Enable TypeScript strict mode and a lint rule that forbids floating promises.
    • Keep every test independent of execution order.
    • Send test code through pull requests and ask developers to review it like product code.

    Watch out for

    • Copying test code from tutorials without understanding async, leading to false passes.
    • Abstracting too early so the tests are harder to read than the feature itself.

    Checkpoint project: Price calculator with unit tests

    Write a TypeScript module that computes a cart total with discount codes and tax, then unit test it with Vitest using the decision table from stage 02. It passes when tests run in CI, boundary cases are covered and no promise is left unawaited.

    • TypeScriptTypeScript
    • Python
    • VitestVitest

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4IntermediateIn a Playwright test, page.click('#save'); expect(page.getByText('Saved')).toBeVisible(); has no await. What is the problem?
    2. Question 2 of 4IntermediateSetup creates three independent test users with await Promise.all([...]). What does that give you?
    3. Question 3 of 4IntermediateTest B only passes when test A runs first, because A creates the user that B logs in with. What is the consequence?
    4. Question 4 of 4IntermediateA pull request changes a shared date-formatting helper used by invoices and reports. Where should you focus testing?
  2. 05Stage 05, 4 weeksAPI testing and contract testingTest APIs manually and automatically, validate schemas and protect the frontend-backend contract with contract tests.
    Most integration bugs I have hit came from the backend changing a response shape without the frontend knowing. Contract testing is the thing I wish my teams had adopted earlier.

    What to learn

    Postman and Bruno
    Postman is strong on cloud collaboration, workspaces and mock servers. Bruno stores collections as plain text files inside the repo, so reviewing and versioning them with Git feels natural for teams that want everything next to the code. Whichever you use, learn environment variables, pre and post request scripts, and running collections from the CLI in CI.
    Designing API tests
    Beyond the happy path, test validation (400, 422), authentication and authorization (401, 403, accessing someone else's resource), idempotency, pagination, rate limits and concurrency. Broken object level authorization (BOLA) tops the OWASP API Security Top 10.
    Schema validation
    Treat OpenAPI as the source of truth and validate responses with JSON Schema (Ajv) or Zod to catch type changes, missing fields and unexpected nulls. Schema checks are cheap and catch more integration bugs than comparing individual values.
    Contract testing with Pact
    Pact is consumer-driven: the consumer records its expectations in a pact file and the provider verifies it in its own pipeline. The Pact Broker versions contracts, and can-i-deploy tells you whether both sides are compatible before release. Contract tests replace many slow E2E tests that only existed to check integration.
    API tests in code
    Playwright's request fixture (APIRequestContext) calls APIs inside the same test runner, handy for seeding data or testing APIs alongside the UI. Combined with schema validation and test data builders, you get an API suite that is far faster and more stable than E2E.

    Do

    • Keep API collections in the repo and run them in CI on every pull request.
    • Validate the schema of every response before asserting specific values.
    • Test authorization by using user A's token to access user B's data.
    • Run can-i-deploy before every release when you use contract testing.

    Watch out for

    • Only checking for status 200 without validating the body and schema.
    • Using contract tests to check provider business logic, when they should only lock the shape of the interaction.

    Checkpoint project: API suite with a contract

    Write a Bruno collection and a Playwright API suite for Restful Booker or your own API, with schema validation via Zod or Ajv. Add one Pact consumer test for a single endpoint. It passes when both run in CI and include at least three authentication and authorization failure cases.

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4IntermediateHow do you test GET /orders/{id} for broken object level authorization (BOLA)?
    2. Question 2 of 4IntermediateWhy validate each response against the OpenAPI schema before asserting specific values?
    3. Question 3 of 4IntermediateWhat should a Pact contract test between a web app and an orders API verify?
    4. Question 4 of 4IntermediateBefore releasing a new consumer version, the team runs can-i-deploy against the Pact Broker. What does it answer?
  3. 06Stage 06, 5 weeksUI automation with PlaywrightBuild a Playwright E2E suite that is stable, readable, runs in parallel and can be debugged with traces.
    This is the part I have done most myself. The biggest lesson: flaky tests were almost always my fault for waiting the wrong way or sharing data, very rarely Playwright's.

    What to learn

    User-facing locators
    Prefer getByRole, getByLabel and getByText, then getByTestId, and avoid long CSS selectors and XPath tied to DOM structure. Role-based locators are resilient and indirectly check accessibility. Playwright locators are lazy and strict, so matching several elements throws instead of silently picking one.
    Auto-waiting and web-first assertions
    Playwright waits for elements to be visible, enabled and stable before acting. Assertions like toBeVisible and toHaveText retry until the timeout. That is why you never need waitForTimeout; a hard sleep is a sign the test is wrong.
    Fixtures and state isolation
    test.extend lets you build fixtures such as a logged-in user, seeded data or page objects with clear setup and teardown. Use a setup project with storageState to log in once and reuse the session. Every test runs in its own browser context, so tests stay independent and parallelizable.
    Page objects and alternatives
    The Page Object Model groups locators and actions per page and suits large suites, but easily grows into an abstraction layer that is hard to read. Alternatives include feature-level fixtures, helpers named after user actions, or keeping locators inline while the suite is small. Choose just enough abstraction for the suite's size.
    Network mocking and time
    page.route lets you mock or modify responses to test error, empty and loading states the backend cannot easily reproduce. HAR replay runs tests against recorded data. page.clock controls time for date-dependent features like session expiry or countdowns.
    Handling flaky tests
    Record a trace on first retry and open Trace Viewer to inspect DOM, network and console step by step. Use --repeat-each to reproduce flakiness locally. Common causes are data races, order dependence, animations and shared environments; retries are a bandage, so isolate and fix the root cause.

    Do

    • Make getByRole your default locator and add data-testid only when nothing better exists.
    • Never use waitForTimeout; rely on web-first assertions.
    • Log in through a setup project and storageState instead of through the UI in every test.
    • Configure trace: 'on-first-retry' and track the flake rate per test.
    • Quarantine flaky tests with an owner and a deadline instead of letting them stay skipped forever.

    Watch out for

    • Writing E2E tests for every edge case that belongs in unit or API tests.
    • Letting tests share one account and dataset, which breaks under parallel runs.
    • Cranking up retries to keep the pipeline green and hiding real race-condition bugs.

    Checkpoint project: E2E suite for a demo shop

    Write 10 to 15 Playwright tests for Sauce Demo or your own app, covering login via storageState, checkout and error states via page.route. It passes when the suite runs in parallel, contains no waitForTimeout and survives --repeat-each=10 with zero failures.

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4Intermediateawait page.getByRole('button', { name: 'Delete' }).click() runs on a page with two matching Delete buttons. What happens?
    2. Question 2 of 4IntermediateA test is flaky because the 'Saved' toast sometimes appears after 2 seconds. Which fix is right?
    3. Question 3 of 4IntermediateEvery test in a 300-test suite logs in through the UI first. What is the recommended improvement?
    4. Question 4 of 4IntermediateWhy is cranking up retries to keep the pipeline green a risky habit?
  4. 07Stage 07, 3 weeksCI, reporting, test data and visual testsRun tests in the pipeline with sharding, clear reports, isolated test data and screenshot-based UI checks.
    Tests only matter when they run automatically and someone reads the results. I once had a suite that ran fine locally but nobody looked at its report, which made it as good as absent.

    What to learn

    Tests in the pipeline
    Run fast checks (lint, unit, API, contract) on every pull request, an E2E smoke set before merge and the full suite on a schedule or before release. Use the official Playwright container so browsers match between local and CI. Cache dependencies and install only the browsers you need.
    Parallelization and sharding
    Playwright runs workers in parallel on one machine and splits shards across machines with --shard. Use the blob reporter on each shard, then merge-reports into a single HTML report. Tests must be data-independent to parallelize safely.
    Reporting and signal
    A report should answer quickly: where did it fail, is it flaky, is there a trace or video. Publish JUnit results so failures show on the pull request, and track duration and flake rate over time instead of looking at single runs.
    Test data management
    Create data through APIs or factories per test instead of sharing a hand-edited database. Use Faker with a fixed seed for random yet reproducible data. Testcontainers spins up throwaway databases for integration tests, and you always need a cleanup strategy or namespaced data.
    Visual regression
    Playwright's toHaveScreenshot compares pixels against a baseline, so capture in a fixed environment (container, fonts, viewport) and mask dynamic regions like timestamps or avatars. Components can be visually tested through Storybook. ARIA snapshots (toMatchAriaSnapshot) complement this by checking structure instead of pixels, with far less noise.

    Do

    • Split the pipeline into a fast tier and a full tier, and gate merges on the fast tier.
    • Upload traces, videos and the HTML report as artifacts for every failed run.
    • Generate fresh data for each test and never depend on existing staging data.
    • Update screenshot baselines through a reviewed pull request, never blindly in bulk.

    Watch out for

    • Capturing visual baselines on a laptop and comparing on CI, causing font and rendering diffs.
    • Letting a 40-minute E2E suite block every pull request.

    Checkpoint project: A complete test pipeline

    Configure GitHub Actions to run API tests, contract tests and Playwright E2E across 3 shards, merge into one HTML report and upload traces on failure. Add 3 visual tests with masked dynamic regions. It passes when the pipeline finishes under 10 minutes and two consecutive runs give the same result.

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4IntermediateYou split a Playwright suite across 4 CI machines with --shard. How do you get a single HTML report?
    2. Question 2 of 4IntermediateScreenshot tests pass locally but fail on CI with tiny font and anti-aliasing diffs. What is the most likely cause?
    3. Question 3 of 4IntermediateTests fail on staging because someone edited a shared test account. Which approach fixes this best?
    4. Question 4 of 4IntermediateWhy gate pull requests on a fast tier and run the full E2E suite on a schedule or before release?
  5. 08Stage 08, 3 weeksMobile testing basicsUnderstand what makes mobile testing different and automate a few key flows with Maestro or Appium.
    I have only worked next to mobile developers and mobile testers, but that was enough to see that mobile adds a whole layer of risk the web does not have: permissions, flaky networks, the app being killed mid-flow.

    What to learn

    What is different on mobile
    Device and OS fragmentation, permissions (camera, location, notifications), app lifecycle (background, killed, restored), deep links, poor networks and offline mode. Base your device matrix on real user analytics, not on the nicest phones.
    Maestro
    Maestro describes flows in YAML, runs against release builds without code instrumentation, and has built-in waiting and retries that reduce flakiness. It is a great fit for fast smoke tests on React Native, Flutter or native apps. When logic gets complex, YAML can become hard to maintain.
    Appium
    Appium uses the WebDriver protocol with separately installed drivers such as UiAutomator2 for Android and XCUITest for iOS, and supports many languages. It is flexible and common in enterprises, at the cost of heavier setup and careful waiting strategies to avoid flakiness.
    Native tools and device clouds
    Espresso (Android) and XCUITest (iOS) are the fastest and most stable but platform-specific, and are usually written by mobile developers. Emulators and simulators cover most tests, while device clouds or physical devices are needed for performance, sensors and vendor-specific bugs.

    Do

    • Add stable accessibility identifiers or testIDs to every element you need to automate.
    • Test interruptions such as incoming calls, backgrounding and losing the network.
    • Choose the device matrix from real user data and review it every quarter.

    Watch out for

    • Testing only on the newest emulator and ignoring the low-end devices real users have.
    • Porting web test habits to mobile without accounting for app lifecycle and permissions.

    Checkpoint project: Mobile smoke tests with Maestro

    Write 3 Maestro flows for a sample app: launch, log in, perform one key action and handle a permission dialog. It passes when the flows run on an Android emulator in CI and you can write one page comparing when Appium would be the better choice.

    • Mobile
    • Maestro
    • Appium

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4IntermediateHow should you choose the devices in a mobile test matrix?
    2. Question 2 of 4IntermediateA user fills a long form, switches to the camera app, and comes back to an empty form. Which test would catch this?
    3. Question 3 of 4IntermediateWhy is Maestro a good fit for fast smoke tests across React Native, Flutter and native apps?
    4. Question 4 of 4IntermediateYour Appium tests break every time designers tweak copy or layout. What is the most effective fix?

Advanced09–10

  1. 09Stage 09, 5 weeksPerformance, accessibility and securityDesign and run load tests with k6, check accessibility both automatically and manually, and perform basic security checks.
    As a frontend developer I learned accessibility first, then saw that QA is who keeps it from regressing. Performance and security I am still learning, and they demand a very different mindset from functional testing.

    What to learn

    Load testing with k6
    k6 scripts are JavaScript; you configure scenarios with executors such as ramping-vus or constant-arrival-rate and set thresholds (for example p95 under a target, error rate under 1%) so the test fails automatically. Distinguish smoke, load, stress, spike and soak tests, since each answers a different question.
    Reading performance results
    Look at percentiles (p95, p99) rather than averages, and correlate with CPU, memory, connection pools and server-side traces. Test on an environment sized like production, and for the frontend track Core Web Vitals (LCP, INP, CLS) through Lighthouse and real user data.
    Accessibility testing
    Run axe-core via @axe-core/playwright to catch automatable issues like missing labels, contrast and invalid ARIA, but automated tools only find part of the problems. The rest needs manual testing: keyboard only, focus order, screen readers (NVDA, VoiceOver) and 200% zoom. The reference is WCAG 2.2 level AA, and the European Accessibility Act has made it a legal requirement for many products.
    Security basics for testers
    Know the OWASP Top 10 and OWASP API Security Top 10: broken access control, injection, authentication failures, misconfiguration. Try IDOR by changing IDs in requests, check security headers, and run a DAST scan such as the ZAP baseline in CI. Deep security work belongs to specialists, but testers catch a lot of authorization bugs.
    Chaos and resilience
    Test behavior when dependencies are slow or down: timeouts, retries, circuit breakers and the error message users see. Start small by mocking network failures in Playwright or stopping a service in staging before reaching for full chaos engineering.

    Do

    • Define performance goals as k6 thresholds before running the test.
    • Add axe checks to E2E for key pages and block merges on serious violations.
    • Check every new feature with the keyboard alone before calling it done.
    • Only run load tests and security scans against environments you are authorized to test.

    Watch out for

    • Reading the average response time and ignoring the p99 tail.
    • Assuming a clean axe score means the page is accessible.
    • Load testing production or a third-party API without warning anyone.

    Checkpoint project: Non-functional quality report

    Write a k6 script with two scenarios (load and spike) and thresholds for one of your APIs, add axe checks to three key pages and run a ZAP baseline scan in CI. It passes when a one-page report states thresholds, results, the top three issues and proposed fixes.

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4AdvancedA load test reports an average response time of 180 ms and a p99 of 4 s. What should you conclude?
    2. Question 2 of 4AdvancedWhich k6 option makes a run fail automatically when latency regresses?
    3. Question 3 of 4Advancedaxe reports zero violations on the signup page. Why can you not call the page accessible yet?
    4. Question 4 of 4AdvancedLogged in as yourself, which test checks for an IDOR vulnerability?
  2. 10Stage 10, 5 weeksQuality engineering and AI in testingMeasure quality with meaningful metrics, test safely in production and use AI both to speed up testing and to evaluate AI features.
    I come to AI from the side of integrating LLMs into products, and that made one thing clear: testing an AI feature is much harder than letting AI write tests. Both still need a human holding the final judgment.

    What to learn

    Quality metrics
    Track escaped defects, flake rate, pipeline feedback time and DORA metrics such as change failure rate and recovery time. Code coverage only tells you which lines never ran, not whether the tests are good. Pick a few metrics and tie each to a concrete decision.
    Observability and testing in production
    OpenTelemetry links traces from frontend to backend, so a bug report can carry a trace ID instead of a vague description. Synthetic monitoring runs key flows against production on a schedule, alongside SLOs and error-budget alerts. Testing in production does not replace pre-release testing; it catches what staging can never reproduce.
    Feature flags and safe releases
    Feature flags decouple deploy from release, enabling canaries, percentage rollouts and kill switches. OpenFeature is an open standard that avoids vendor lock-in. QA needs to test both states of a flag, the important flag combinations, and have a plan for removing stale flags.
    LLM and agent test generation
    Playwright ships test agents (planner, generator, healer) that run inside agent loops such as VS Code and Claude Code, and Playwright MCP lets agents drive the browser through the accessibility tree. They speed up writing test scaffolding, but humans still decide what to test and review assertions, because AI tends to encode current behavior even when that behavior is wrong.
    Self-healing tests
    Self-healing repairs locators or steps when the UI changes, cutting maintenance. The risk is masking real bugs, for example a button with a wrong new label still being accepted. Treat every healer change as a pull request that needs review, never an automatic merge.
    Evaluating AI features
    LLM output is non-deterministic, so exact-match assertions are not enough. You need an eval dataset from real cases, scoring with rules, semantic similarity or an LLM-as-judge calibrated against human labels, and evals running as regression tests in CI with tools like promptfoo. Do not forget red-teaming: prompt injection, data leakage and out-of-scope behavior.

    Do

    • Attach a trace ID or request ID to every bug found in an environment with observability.
    • Test every feature flag in both its on and off states before rollout.
    • Review every AI-generated test and fix as you would code from a new teammate.
    • Build eval datasets from real user failures and grow them after every incident.

    Watch out for

    • Setting KPIs on coverage or bug counts, so the team optimizes numbers instead of quality.
    • Letting a healer fix tests unattended and turning real bugs into green tests.
    • Judging an AI feature by trying a handful of prompts by hand and calling it fine.

    Checkpoint project: Quality dashboard and eval suite

    Use Playwright test agents to generate additional tests for the app from stage 06, review them and record how much needed manual fixing. Build a 30-case eval suite for a small LLM feature (such as summarization or classification) that runs in CI. It passes when a simple dashboard shows flake rate, pipeline duration and eval scores over time.

    Quick check

    0/4 answered · 0 correct

    Get at least 3 of 4 right to mark this stage as passed.

    1. Question 1 of 4AdvancedWhy is code coverage a weak KPI for test quality?
    2. Question 2 of 4AdvancedA new checkout ships behind a feature flag rolling out to 10% of users. What must QA test before rollout?
    3. Question 3 of 4AdvancedA self-healing tool updates a locator after a button label changed from 'Pay' to 'Pya'. Why must such fixes go through review?
    4. Question 4 of 4AdvancedHow should you test an LLM-powered support answer feature before each release?

What matters right now, and where things are heading in the next few years.

Now

  • Playwright is the default for web E2E

    For new web projects Playwright is close to the default choice thanks to built-in auto-waiting, tracing and parallelism. Selenium and Cypress remain common in older codebases, so being able to read them still pays off.

  • AI agents write and fix tests

    Playwright's test agents and Playwright MCP bring generating, running and repairing tests into the editor and agent loops. The key skills shift toward test design, writing clear intent and reviewing AI output.

  • QA becomes quality engineering

    Developers increasingly write their own tests, while QA focuses on strategy, test infrastructure, exploratory testing and coaching. The lines between SDET, QA and platform engineering keep blurring.

  • Accessibility is mandatory

    The European Accessibility Act and similar regulations have made WCAG 2.2 AA a release criterion for many products. Teams need both automated checks in CI and regular manual audits.

Next

  • Evals become a QA discipline

    As more products ship LLM and agent features, evaluating non-deterministic output will become a core QA skill. Start learning eval dataset design, LLM-as-judge and red-teaming now.

  • Agentic testing at scale

    Agents will explore apps, propose tests and maintain suites far more than they do today. A tester's value will sit in defining risk, the oracle (what correct looks like) and the controls that stop AI from legitimizing bugs.

  • Quality driven by production signals

    Observability, feature flags and progressive delivery make production data part of the test strategy. Learning OpenTelemetry, SLOs and how to read traces lets testers work as peers with SREs.

  • Contracts replace slow E2E

    Contract testing, schema-first APIs and component tests will carry more of the integration checking, with E2E kept for the most critical journeys. Prepare by learning OpenAPI, Pact and the habit of choosing the right test level.

By the end of this map you can

  • You can build a risk-based test strategy and explain why each test lives at its level.
  • You can design test cases with equivalence partitioning, boundary values, decision tables and state transitions, and run chartered exploratory sessions.
  • You can write API tests with schema validation and Pact contract tests that run in CI.
  • You can build and maintain a stable, parallel Playwright E2E suite and debug flakiness with traces.
  • You can run k6 load tests, audit accessibility against WCAG 2.2 and perform basic security checks.
  • You can use AI agents to generate tests under control and build an eval suite for an LLM feature.
  • You can measure quality with meaningful metrics and use observability and feature flags to reduce release risk.

Related articles

All articles

Type-Level TypeScript for API Contracts You Can't Misuse

Conditional types and infer, key remapping, template literal types that turn "/users/:id/posts/:postId" into typed params, a fetch client derived from a route map, typed errors, branded IDs, satisfies and const type parameters, a Zod bridge so the types aren't lies — and when to stop.

Tooling & workflow16 min

Other roles

Roadmap

Frontend Engineer

My main role

Building web interfaces that stay fast, accessible and maintainable as products grow

10 stages, 51 topics, ~34 weeks

Designs, builds and runs the APIs, data and services behind every product

10 stages, 52 topics, ~37 weeks

Build iOS and Android apps that feel smooth, work offline and ship safely

10 stages, 50 topics, ~34 weeks

Builds infrastructure, pipelines and platforms so teams ship fast, safely and reliably

10 stages, 56 topics, ~42 weeks

Build products on top of LLMs: APIs, RAG, agents, evals and running it all in production

10 stages, 58 topics, ~31 weeks