1. Cheat sheets
  2. Engineering Roles

9 minReference

QA and test automation cheat sheet

Testing on a few screens: test design techniques, what to test at which layer, a bug report template, Playwright, Jest and Vitest commands, API and accessibility checks, fixes for flaky tests, load testing and UAT sign-off. Keep it open while you plan tests or write them.

Test design techniques

Each technique finds a different kind of bug with fewer test cases than guessing. The examples use Mangrove's app and Store app (Test design).

TechniqueUse it whenMangrove exampleLesson
Equivalence partitioningMany inputs behave the same wayOrder quantity: one test for 1 to 99 (valid), one for 0 or less, one for 100 or moreTest design
Boundary valuesA rule has a limitMax 99 per item: test 0, 1, 98, 99, 100; free delivery from $20.00: test $19.99 and $20.00Test design
Decision tableSeveral conditions combine into one outcomeDiscount = member? × coupon? × promo item? with the expected price for each of the 8 rowsTest design
State transitionSomething moves through statesOrder: placed, packed, out for delivery, delivered, cancelled; test every allowed move and a few forbidden onesTest design
PairwiseToo many combinations of settingsAndroid version × screen size × network × language: cover every pair, not every combinationTest design
Error guessingYou know where bugs usually hideEmpty cart, emoji in names, double tap on "Pay", app killed mid-checkoutExploration
Exploratory sessionNew feature, unclear risksCharter: "Explore receiving a delivery with a damaged pallet, to find where stock counts go wrong", 60 minutes, notesExploration
Risk-based selectionNot enough time to test everythingTest payment and stock first, profile pictures last; likelihood × impactWhy we test, Test strategy

What to test at which layer

Most checks belong low in the pyramid, where they are fast and pin the bug to one place. Keep end-to-end tests for the few journeys that must never break (Test strategy).

LayerTestsRough count and speedTools
Static checksTypes, lint rules, formattingWhole repo in secondsTypeScript, ESLint, Prettier
UnitOne function or component: price rounding, VAT, discount rulesHundreds to thousands, milliseconds eachJest, Vitest, React Testing Library
Integration and APIAn endpoint with a real database; auth, validation, status codesTens to hundreds, under a second eachSupertest, Playwright request, a test Postgres
ContractThe app and the API agree on request and response shapesOne set per consumer-provider pairPact, OpenAPI schema checks
End-to-endBrowse, add to cart, check out; receive a delivery5 to 30 journeys, seconds eachPlaywright, Detox or Maestro for mobile
Exploratory and UATWhat scripts miss; whether it fits the real jobTime-boxed sessionsCharters, a test store such as Ama's

Bug report template

One bug per report. A developer should be able to reproduce it without asking you anything (Bugs and UAT).

Markdown
Title: Checkout total ignores coupon when cart has a promo item (Android)

Environment: Mangrove app 4.12.0 (build 812), Android 14, Pixel 7, staging API
Severity: Major   Priority: High   Found by: exploratory session, checkout charter

Steps to reproduce
1. Sign in as test user qa.member@example.test (member)
2. Add "Basmati rice 5 kg" (promo item) and "Milk 1 L" to the cart
3. Apply coupon SAVE10
4. Open the checkout screen

Expected: discount line -$0.12 (10% of Milk 1 L at $1.20); total $16.38
Actual:   total $16.50; coupon shows "applied" but no discount line

Frequency: 5 of 5 tries. Does not happen without the promo item.
Evidence: screen recording, request id 7f3c2a in API logs
Notes: iOS 17 on the same build shows the right total
FieldMeansWho sets itExample
SeverityHow bad the effect isTesterCritical: tills cannot take payment. Minor: a typo on a receipt
PriorityHow soon to fixProduct owner with the teamA typo in the festival-sale banner can be minor severity but top priority
StatusWhere it isWhoever moves itNew, triaged, in progress, ready to test, closed, won't fix

Playwright: "I want to..."

Commands for @playwright/test run from the project folder (Playwright E2E).

I want to...CommandLesson
Add Playwright to a projectnpm init playwright@latestPlaywright E2E
Run every testnpx playwright testPlaywright E2E
Run one file, or tests whose title matchesnpx playwright test tests/checkout.spec.ts, -g "applies coupon"Playwright E2E
Run in one browser only--project=chromiumPlaywright E2E
Watch the browser--headed; step through with --debugPlaywright E2E
Use the interactive runnernpx playwright test --uiPlaywright E2E
Record a test by clickingnpx playwright codegen https://staging.example.testPlaywright E2E
See what happened in a failed run--trace on, then npx playwright show-trace trace.zipStable CI
Open the HTML reportnpx playwright show-reportPlaywright E2E
Hunt a flaky test--repeat-each=20 --workers=1 on that testStable CI
Update screenshot baselines--update-snapshots (short: -u)Playwright E2E
List tests without running them--listPlaywright E2E

Locators and assertions

Find elements the way a user does. Role and label locators survive redesigns; CSS paths tied to layout break every sprint. Web-first assertions such as toBeVisible retry until a timeout, so you never need a fixed sleep (Playwright E2E, Accessibility).

TypeScript
import { test, expect } from '@playwright/test';

test('member coupon lowers the total', async ({ page }) => {
  await page.goto('/cart');
  await page.getByLabel('Coupon code').fill('SAVE10');
  await page.getByRole('button', { name: 'Apply' }).click();
  await expect(page.getByRole('status')).toHaveText('Coupon applied');
  await expect(page.getByTestId('cart-total')).toHaveText('$14.85');
});
Prefer, in this orderExampleAvoid
Role and accessible namegetByRole('button', { name: 'Place order' })page.locator('div.btn-primary:nth-child(3)')
Form labelgetByLabel('Email')Placeholder text that changes with copy edits
Visible textgetByText('Out of stock')Long XPath expressions
Test id, when nothing else is stablegetByTestId('cart-total') with data-testid in the markupGenerated class names
Auto-retrying assertionstoBeVisible(), toHaveText(), toHaveURL(), toHaveCount()page.waitForTimeout(3000)

Jest and Vitest side by side

The APIs are nearly the same; Vitest uses vi where Jest uses jest. Vitest watches by default in a terminal and runs once in CI (Unit and API tests, Testing React).

I want to...JestVitestLesson
Run oncenpx jestnpx vitest runUnit and API tests
Watch while I codenpx jest --watchnpx vitestUnit and API tests
Run tests whose name matchesnpx jest -t "rounds VAT"npx vitest run -t "rounds VAT"Unit and API tests
Measure coveragenpx jest --coveragenpx vitest run --coverage (needs @vitest/coverage-v8)Test strategy
Fake a functionjest.fn()vi.fn()Unit and API tests
Replace a modulejest.mock('./payments')vi.mock('./payments')Unit and API tests
Control timejest.useFakeTimers()vi.useFakeTimers()Debug and test
Compare objects, not identitytoEqual for values, toBe for primitives and same object; await expect(p).rejects.toThrow() for promisesDebug and test

API testing checklist

Run each row against every new endpoint. curl -i shows the status line and headers; add -H 'Content-Type: application/json' -d '{"qty":2}' to send a body (API testing).

CheckExample on POST /stores/S-014/ordersExpectLesson
Happy pathValid body and token201, the new id, a response that matches the schemaAPI testing
No or bad tokenDrop the Authorization header401API testing
Someone else's resourceA token for store S-102403 or 404, never the dataAccess control
Invalid inputMissing field, qty -1, qty "two", a 10 MB body400 or 422 with a clear message; nothing savedAPI testing
Retry the same requestSame Idempotency-Key twiceOne order, the same response both timesUnit and API tests
ConflictsTwo requests for the last item in stockOne succeeds, one gets 409API testing
ListsPage past the end; a filter with no resultsEmpty list, not an error; stable orderAPI testing
LimitsFire 200 requests in a minute429 with Retry-AfterAPI testing
ContractThe app's expected shape against the providerPact or schema check passes in CIContract tests

Flaky tests: if you see X, reach for Y

A flaky test is a bug in the test, the app or the environment. Quarantine it with an owner and a date; do not just add retries and forget it (Stable CI).

You seeLikely causeFixLesson
Passes locally, fails in CISlower machine; different time zone, locale or screen sizeWeb-first assertions; set timezoneId, locale and viewport in configStable CI
Fails only when run with other testsShared data or order dependenceEach test creates its own user and data; no shared stateStable CI
"Element not found" now and thenClicking before the page is ready; brittle selectorRole or label locators; wait for a visible state, not a sleepPlaywright E2E
Fails around midnight or month-endReal clock in the testFake timers or a fixed clock (page.clock in recent Playwright)Debug and test
Fails when a third-party service is slowReal network callsMock at the boundary (page.route, MSW); test the real service in a separate contract or smoke testContract tests
Screenshot diff on every runAnimations, fonts, dynamic datesDisable animations, mask dynamic areas, run in one fixed container imageStable CI

Accessibility quick checks

Automated scanners such as axe (@axe-core/playwright) catch only part of the problems. The keyboard and a screen reader catch most of the rest. Targets are WCAG 2.2 level AA (Accessibility, Accessible and fast).

CheckHowPass whenLesson
Keyboard onlyTab, Shift+Tab, Enter, Space, arrow keys, EscEvery action works, in a sensible order, with no trapAccessibility
Visible focusTab through the pageYou can always see where focus isAccessibility
Text contrastDevTools or a contrast checker4.5:1 for normal text; 3:1 for large text and for icons and borders that carry meaningAccessibility
Names and labelsScreen reader or the accessibility tree in DevToolsEvery control and input says what it is; images have useful alt text or alt="" if decorativeAccessibility
Zoom and reflowZoom to 200%, then a 320 px wide windowNothing is cut off; no sideways scrolling for textAccessibility
Target sizeMeasure tap targetsAt least 24 by 24 CSS pixels (WCAG 2.2); 44 or 48 is kinder on phones and scannersAccessibility
ErrorsSubmit a form wronglyThe error is in text, next to the field, and announcedForms
Screen reader passNVDA on Windows, VoiceOver on macOS and iOS, TalkBack on AndroidThe main journey can be completed by earAccessibility, Test and release

Load testing in one screen

Test against staging sized like production, never against production without an agreed window. Decide the pass mark before you run: for example p95 under 500 ms and under 1% errors at 4 times normal traffic, Mangrove's festival peak (Load testing).

JavaScript
// k6 script: run with  k6 run browse.js
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 50,
  duration: '5m',
  thresholds: {
    http_req_duration: ['p(95)<500'],
    http_req_failed: ['rate<0.01'],
  },
};

export default function () {
  const res = http.get('https://staging.example.test/api/products?store=S-014');
  check(res, { 'status is 200': (r) => r.status === 200 });
  sleep(1);
}
Test typeShapeAnswersLesson
SmokeA few users for a minuteDoes the script and the system work at all?Load testing
LoadExpected peak for 15 to 60 minutesDo we meet the targets on a busy day?Load testing
StressKeep raising load past the peakWhere does it break, and how: slowly or all at once?Load testing
SpikeJump from normal to peak in secondsWhat happens when a push notification goes to 2 million customers?Load testing
SoakNormal load for hoursMemory leaks, filling disks, connection pools that never give backLoad testing

UAT and release sign-off

User acceptance testing asks whether the change fits the real job, done by the people who do it, such as Ama's store team on real handheld scanners. Agree entry and exit criteria before it starts (Bugs and UAT, Change and UAT).

  • Entry: build deployed to the UAT environment, test data loaded, known issues listed, testers briefed with scenarios written in business words.
  • During: testers log issues in one place; QA triages daily with the product owner.
  • Exit: every scenario run; no open critical or major bugs; minor ones accepted in writing with a fix date.
  • Sign-off note: build number, scenarios passed, open issues accepted, who signed and when, and the rollback plan.

Glossary

Plain definitions of the testing terms used across the QA courses.

Acceptance criteria
The conditions a story must meet to be accepted, often written as Given, When, Then. Stories and criteria
Boundary value
A value at the edge of a rule, such as the maximum quantity, where off-by-one bugs live. Test design
Charter
A one-line mission for an exploratory session: explore a target, with a resource, to find a kind of risk. Exploration
Code coverage
The share of code lines or branches that tests ran; it shows what is untested, not that tested code is right. Test strategy
Contract test
A test that checks a consumer and a provider agree on the shape of requests and responses. Contract tests
End-to-end (E2E) test
A test that drives the whole system through the user interface, as a user would. Playwright E2E
Exploratory testing
Designing and running tests at the same time, learning as you go, inside a time box. Exploration
Fixture
Setup a test needs, such as a signed-in page or a seeded store, created fresh for each test. Playwright E2E
Flaky test
A test that sometimes passes and sometimes fails on the same code. Stable CI
Mock, stub, fake
Stand-ins for real dependencies: a stub returns fixed answers, a mock also checks how it was called, a fake is a simple working version. Unit and API tests
Regression
Something that used to work and broke after a change. Why we test
Severity and priority
Severity is how bad the bug's effect is; priority is how soon it should be fixed. Bugs and UAT
Smoke test
A few quick checks that the most important things work, run right after a deploy. Test strategy
Test oracle
How you know the right answer: a spec, a calculation, an older version or a person's judgement. Test design
Test pyramid
Many fast low-level tests, fewer integration tests and only a few end-to-end tests. Test strategy
Trace
Playwright's recording of a run: actions, DOM snapshots, network and console, for debugging failures. Stable CI
UAT
User acceptance testing: the people who will use the change confirm it fits their work. Bugs and UAT
WCAG
Web Content Accessibility Guidelines; level AA of version 2.2 is the usual target. Accessibility
Web-first assertion
An assertion that retries until the page reaches the expected state or a timeout passes. Playwright E2E
p95 latency
The response time that 95 out of 100 requests are faster than; the usual load-test target. Load testing

Courses on Kolom

  • Playwright documentation at playwright.dev. The guides on locators, assertions and the trace viewer are short and exact.
  • The Practical Test Pyramid by Ham Vocke, at martinfowler.com. What to test at each layer, with examples.
  • WCAG 2.2 quick reference at w3.org/WAI. Every success criterion with techniques, filterable by level.
  • Grafana k6 documentation at grafana.com/docs/k6. Test types, thresholds and scenarios.
  • Explore It! by Elisabeth Hendrickson. The best short book on charters and exploratory testing.