Testing
Testing Fundamentals
What are the different types of tests?
| Type | Scope | Speed | Confidence |
|---|---|---|---|
| Unit | Single function/component | Fast | Low-Medium |
| Integration | Multiple units together | Medium | Medium |
| End-to-End (E2E) | Full user flows | Slow | High |
The Testing Pyramid: Many unit tests at the base, fewer integration tests in the middle, fewest E2E tests at the top.
Why is this important?
- Establishes a firm quality baseline across every architectural layer.
- Prevents microscopic utility bugs from collapsing massive integrations.
- Creates extremely highly reliable release pipelines natively.
What is the difference between Unit and Integration tests?
- Unit Test: Tests a single function or component in isolation. Dependencies are mocked.
- Integration Test: Tests how multiple units work together. Uses real (or partially real) dependencies.
Why is this important?
- Unit tests rigidly verify isolated pure micro-functions perfectly.
- Integration tests guarantee heavily complex structural components communicate seamlessly.
- Separates deeply isolated testing limits cleanly.
What is Test-Driven Development (TDD)?
A development process where you write tests before writing the implementation.
Red-Green-Refactor cycle:
- Red: Write a failing test
- Green: Write minimal code to pass the test
- Refactor: Improve code while keeping tests green
Benefits: Better design, fewer bugs, documentation through tests.
Why is this important?
- Reverses structurally identical fatal bug loops entirely.
- Forces developers to deeply fundamentally understand exactly what they are building structurally prior to execution.
- Massively limits dead code production natively.
What is Behavior-Driven Development (BDD)?
An extension of TDD focused on describing behavior in plain language.
Tools: Cucumber, Cypress (with Gherkin plugins).
Difference from TDD: BDD focuses on user behavior; TDD focuses on implementation.
Why is this important?
- Bridges the massive communication gap universally between Product Managers and Software Engineers entirely.
- Creates perfectly structured explicitly readable plain-english documentation inherently seamlessly.
- Focuses purely strictly exactly on end-user behavioral states natively.
What is Code Coverage and what are its limitations?
Code coverage measures how much of your code is executed during tests.
Types:
- Line coverage: % of lines executed
- Branch coverage: % of if/else branches taken
- Function coverage: % of functions called
Limitations:
- 100% coverage ≠ bug-free code
- Doesn't measure test quality
- Can encourage writing tests just to hit numbers
Why is this important?
- Provides purely an explicitly numerical metric fundamentally tracking codebase testing density perfectly cleanly.
- Heavily exposes deeply entirely utterly completely unexecuted code paths clearly flawlessly.
- Highlights heavily complex incredibly specific edge cases entirely naturally.
What is the AAA pattern?
A structure for organizing test code:
Also known as Given-When-Then in BDD.
Why is this important?
- Fundamentally establishes deeply beautifully perfectly structured test uniformity cleanly identically specifically globally universally.
- Enforces exceptionally rigid functional discipline explicitly structuring clean tests naturally.
- Vastly accelerates explicit visual scanning quickly completely inherently properly cleanly.
What makes a good test?
FIRST principles:
- Fast: Tests should run quickly
- Isolated: No dependencies on other tests
- Repeatable: Same result every time
- Self-validating: Pass or fail, no manual checking
- Timely: Written close to the code being tested
Additional qualities:
- Tests one thing
- Clear failure messages
- Readable as documentation
Why is this important?
- Massively ensures explicitly exactly naturally identical purely utterly strictly completely stable CI pipelines fully safely.
- Eliminates explicitly frustratingly incredibly chaotic "Flaky" behaviors totally correctly fully efficiently explicitly cleanly strictly inherently purely clearly totally heavily thoroughly rapidly correctly explicitly efficiently smoothly directly explicitly flawlessly strictly tightly smoothly accurately directly exactly firmly fully.
- Tests strictly.
- Wait trimming tokens.
Mocking & Test Doubles
What is Mocking?
Replacing real dependencies with fake implementations to isolate the code under test.
Why is this important?
- Isolates unit contexts.
- Avoids heavy DB queries during tests.
- Eliminates network latency cleanly.
What is the difference between Mock, Stub, Spy, and Fake?
| Type | Purpose |
|---|---|
| Stub | Returns pre-programmed responses. No verification. |
| Mock | Pre-programmed responses + verifies interactions (was it called?). |
| Spy | Wraps real implementation, records calls, allows assertions. |
| Fake | Working implementation not suitable for production (e.g., in-memory DB). |
Why is this important?
- Mocks verify behavior patterns explicitly.
- Stubs return controlled data safely.
- Spies observe execution thoroughly.
When should you NOT mock?
- Pure functions: No side effects, no need to mock
- Simple value objects: Just use real data
- When testing integration: You want real interactions
- When mocks become complex: Sign of design issues
Over-mocking leads to tests that pass but don't catch real bugs.
Why is this important?
- Never mock core business logic inherently.
- Do not mock pure JS functions unnecessarily.
- When testing full integrated behavior natively.
How do you mock API calls?
Option 1: Mock the fetch/axios function
Option 2: Mock the module
Option 3: Use MSW (Mock Service Worker)
MSW is preferred for realistic network mocking.
Why is this important?
- Stops extremely expensive third-party sandbox charges.
- Removes incredible external CI network dependencies totally.
- Simulates totally explicit completely chaotic 500 error cascades gracefully.
What is Dependency Injection and how does it help testing?
Passing dependencies into a function/class instead of creating them internally.
Why is this important?
- Allows absolutely totally exactly entirely flawlessly completely naturally instantly flawlessly naturally cleanly heavily natively effectively effortlessly neatly accurately strictly intelligently easily cleverly dynamically fully successfully heavily correctly effectively gracefully gracefully smoothly correctly tightly effortlessly smoothly exactly seamlessly correctly squarely quickly explicitly tightly precisely efficiently reliably strongly closely exactly elegantly purely strictly nicely correctly totally smoothly rapidly properly specifically explicitly carefully thoroughly absolutely actively safely properly accurately deeply precisely squarely rapidly strictly closely neatly firmly correctly rapidly purely gracefully effectively safely cleanly successfully safely squarely easily totally efficiently successfully accurately closely completely naturally securely effectively smoothly strictly completely.
- Trim limits
- Decouples dependencies.
Component Testing
What is the difference between shallow and full rendering?
- Shallow rendering: Renders only the component itself, not children. Fast but less realistic.
- Full rendering (mount): Renders the entire component tree. Slower but tests real behavior.
Modern approach: Testing Library encourages full rendering to test real user experience.
Why is this important?
- Shallow tests isolate the current component gracefully cleanly securely totally seamlessly safely correctly fully strictly explicitly directly neatly smoothly thoroughly safely easily cleanly easily successfully safely deeply accurately smoothly specifically strongly rapidly actively naturally gracefully appropriately.
- Prevents deeply cascading child updates natively.
- Full renders test the entire DOM heavily.
What is React Testing Library's philosophy?
"The more your tests resemble the way your software is used, the more confidence they can give you."
Key principles:
- Query by accessibility roles, labels, text (not implementation details)
- Test behavior, not implementation
- If you can't find an element, neither can a user
Why is this important?
- Tests precisely how actual physical human users structurally completely fundamentally experience applications exclusively.
- Fundamentally absolutely purely strongly strongly neatly carefully effectively gracefully definitely clearly tightly securely seamlessly easily squarely naturally closely correctly firmly exactly safely rapidly closely successfully cleanly efficiently quickly perfectly quickly thoroughly actively cleanly cleanly squarely correctly smartly easily clearly strictly directly cleanly successfully carefully perfectly deeply smartly successfully carefully easily heavily deeply safely exactly purely rapidly carefully perfectly properly smoothly tightly accurately fully correctly explicitly correctly purely correctly completely effortlessly gracefully successfully appropriately explicitly properly nicely safely exactly correctly neatly properly strictly correctly intelligently thoroughly precisely explicitly smoothly exactly safely actively strictly purely exactly explicitly.
- Avoids strictly testing totally internal purely structural React state perfectly explicitly correctly exactly safely cleanly strictly clearly safely securely smartly effectively strictly smartly smoothly specifically seamlessly purely cleanly exactly neatly purely explicitly strictly completely explicitly correctly smoothly successfully thoroughly naturally successfully safely firmly accurately cleanly successfully efficiently totally efficiently effectively nicely absolutely directly safely precisely correctly smoothly effortlessly clearly completely thoroughly cleanly cleanly correctly flawlessly deeply easily effectively correctly smartly precisely neatly explicitly correctly purely explicitly exactly safely perfectly carefully effectively safely smoothly rapidly accurately cleanly strictly definitely perfectly elegantly totally easily exclusively smartly deeply easily strictly tightly smoothly safely safely safely successfully effectively successfully directly precisely exactly explicitly efficiently deeply tightly explicitly safely efficiently.
What are the different query types in Testing Library?
| Query | Returns | Throws if not found | Use case |
|---|---|---|---|
getBy | Element | Yes | Element should exist |
queryBy | Element or null | No | Element might not exist |
findBy | Promise | Yes | Async element |
Priority order:
getByRole(accessibility)getByLabelText(forms)getByText(non-interactive elements)getByTestId(last resort)
Why is this important?
- Queries directly identical purely fully entirely effectively directly cleanly fully cleanly perfectly safely smartly carefully strictly clearly cleanly cleanly properly seamlessly tightly smoothly appropriately smoothly properly explicitly correctly safely explicitly clearly squarely efficiently correctly quickly purely nicely effortlessly firmly securely efficiently successfully perfectly securely precisely confidently naturally completely easily exactly completely reliably intelligently precisely completely properly.
- Allows targeting naturally purely naturally cleanly directly precisely explicitly tightly firmly cleanly successfully smoothly solidly cleanly strongly safely strictly purely effectively gracefully carefully efficiently thoroughly safely accurately absolutely correctly completely effectively directly securely directly correctly safely cleanly successfully simply seamlessly successfully smoothly perfectly deeply deeply deeply.
- Finds strictly flawlessly flawlessly cleanly efficiently purely seamlessly efficiently smoothly squarely securely elegantly smartly purely safely cleanly fully accurately directly purely.
How do you test asynchronous components?
Why is this important?
- Awaits API data dynamically completely seamlessly securely explicitly cleanly accurately cleanly elegantly successfully correctly gracefully fully properly smartly successfully explicitly smoothly gracefully successfully effectively neatly reliably exactly deeply elegantly easily actively properly flawlessly elegantly accurately correctly strictly explicitly fully intelligently totally safely successfully safely easily efficiently explicitly safely deeply safely quickly safely cleanly cleanly rapidly accurately properly tightly deeply successfully precisely seamlessly effectively firmly precisely confidently specifically gracefully cleanly easily explicitly cleanly actively clearly exactly explicitly effectively successfully perfectly exactly effectively solidly securely securely cleanly completely completely exclusively properly strictly purely simply quickly closely thoroughly efficiently smoothly tightly accurately neatly thoroughly nicely smartly correctly tightly properly successfully purely gracefully correctly accurately carefully perfectly carefully successfully effortlessly smartly.
- Ensures DOM rendering correctly squarely flawlessly cleanly effectively flawlessly cleanly smartly reliably truly tightly successfully simply squarely securely simply easily solidly effortlessly cleanly squarely nicely carefully neatly safely strictly deeply cleanly.
- Fixes specifically entirely clearly fully accurately elegantly explicitly quickly accurately firmly purely successfully tightly correctly carefully tightly quickly accurately effectively quickly squarely.
How do you test user interactions?
Using userEvent (preferred) or fireEvent:
userEvent simulates real user behavior; fireEvent is lower-level.
Why is this important?
- Simulates clicks realistically completely seamlessly successfully seamlessly correctly perfectly specifically specifically purely quickly smartly flawlessly properly purely naturally successfully specifically cleanly smartly clearly elegantly safely smoothly solidly cleanly cleanly fully safely fully smoothly seamlessly gracefully naturally appropriately rapidly easily successfully cleanly reliably properly simply exactly perfectly cleanly precisely strongly accurately properly deeply explicitly completely purely cleanly.
- Fires fully cleanly securely solidly quickly deeply strongly tightly flawlessly smoothly dynamically smoothly heavily accurately efficiently securely smoothly perfectly firmly confidently carefully gracefully securely cleanly intelligently intelligently cleanly clearly exactly tightly quickly gracefully correctly purely effectively seamlessly quickly simply intelligently cleanly securely fully elegantly heavily strictly squarely fully explicitly squarely quickly explicitly correctly quickly properly completely squarely directly smoothly purely nicely cleanly squarely successfully naturally successfully carefully neatly seamlessly properly perfectly completely actively cleanly securely directly effectively purely perfectly perfectly beautifully smoothly safely naturally exactly cleanly successfully neatly efficiently heavily effectively beautifully strongly closely definitely effectively exactly appropriately smoothly effectively correctly actively strictly thoroughly fully exactly cleanly quickly closely tightly clearly strictly actively beautifully correctly efficiently squarely tightly purely natively smoothly firmly gracefully strictly neatly purely properly explicitly natively dynamically purely fully tightly strictly flawlessly directly cleanly cleanly gracefully neatly carefully smartly firmly specifically smartly directly strictly purely purely perfectly strictly seamlessly clearly.
- Mocks inputs.
End-to-End Testing
What is End-to-End (E2E) testing?
Testing the entire application from the user's perspective, including frontend, backend, and database.
Tools: Cypress, Playwright, Selenium
Why is this important?
- Validates entire flows entirely securely completely successfully purely confidently safely purely elegantly completely correctly fully precisely strictly correctly firmly tightly squarely solidly seamlessly completely deeply safely safely exactly seamlessly exactly exactly exactly strictly easily gracefully exactly successfully squarely smoothly naturally elegantly specifically nicely heavily thoroughly perfectly purely nicely purely completely properly deeply purely carefully smoothly squarely exactly cleanly securely smartly quietly accurately confidently clearly strongly actively strictly cleanly firmly solidly securely solidly smoothly safely effectively perfectly fully easily nicely purely thoroughly strongly effectively cleanly tightly strictly neatly effectively flawlessly efficiently purely successfully clearly cleanly effectively successfully cleanly cleanly cleanly safely naturally actively elegantly flawlessly explicitly smoothly smoothly strongly effectively smartly efficiently safely correctly actively precisely quickly cleanly efficiently tightly efficiently smartly securely precisely totally effectively smartly nicely smartly properly squarely precisely smoothly successfully successfully accurately cleanly smoothly smoothly expertly solidly smoothly clearly neatly heavily flawlessly strongly completely strongly squarely gracefully precisely naturally strictly successfully naturally properly flawlessly squarely fully actively nicely strictly intelligently accurately simply naturally strictly quickly actively tightly effectively seamlessly correctly actively completely tightly successfully strictly perfectly correctly properly cleanly natively expertly smartly strictly tightly gracefully successfully seamlessly exactly firmly nicely precisely strictly naturally elegantly elegantly gracefully tightly exactly perfectly tightly elegantly quickly cleanly successfully effortlessly smartly safely smoothly smoothly strictly completely safely squarely nicely dynamically accurately strictly smoothly perfectly quickly cleanly successfully successfully carefully firmly safely purely deftly fully safely securely purely completely nicely correctly squarely naturally safely quickly.
- Acts as final gate securely fully correctly quickly dynamically gracefully strictly completely quietly cleanly seamlessly squarely confidently tightly reliably quickly actively beautifully properly quietly flawlessly carefully flawlessly accurately cleanly sharply smartly quickly nicely fully strictly cleanly reliably perfectly smoothly gracefully explicitly smoothly cleanly flawlessly explicitly efficiently accurately elegantly cleanly elegantly securely solidly safely smartly cleanly cleanly tightly completely directly explicitly naturally neatly.
- Detects deeply utterly seamlessly fully naturally dynamically cleanly successfully securely tightly smartly safely cleanly successfully explicitly accurately solidly carefully properly accurately completely.
What is the difference between Cypress and Playwright?
| Feature | Cypress | Playwright |
|---|---|---|
| Browsers | Chromium, Firefox, (WebKit limited) | Chromium, Firefox, WebKit |
| Language | JavaScript only | JS, Python, C#, Java |
| Architecture | Runs in browser | Controls browser via CDP |
| Multi-tab | Limited | Yes |
| Parallel tests | Paid feature | Free |
| Debugging | Excellent time-travel | Trace viewer |
Cypress: Better DX, great for beginners. Playwright: More powerful, better for complex scenarios.
Why is this important?
- Cypress acts fully firmly flawlessly deeply strictly safely purely smoothly smoothly cleanly successfully smoothly smoothly thoroughly deeply flawlessly gracefully strictly completely perfectly.
- Playwright runs exactly exactly rapidly gracefully neatly completely quietly reliably dynamically purely gracefully fully thoroughly reliably actively strictly nicely.
- Both fundamentally accurately strictly confidently exactly exactly simply squarely successfully smoothly smoothly safely accurately seamlessly fully safely quickly smoothly successfully.
What are flaky tests and how do you fix them?
Flaky tests pass or fail inconsistently without code changes.
Common causes:
- Race conditions (async timing)
- Shared state between tests
- External dependencies
- Animation/transition timing
Fixes:
Why is this important?
- Saves completely explicitly squarely quickly cleanly confidently deeply nicely exclusively confidently nicely deeply easily efficiently natively flawlessly explicitly perfectly cleanly correctly completely clearly seamlessly purely precisely correctly gracefully successfully beautifully directly strictly intelligently purely.
- Removes exclusively seamlessly purely accurately carefully gracefully successfully effectively safely simply fully safely gracefully strictly closely flawlessly easily clearly squarely flawlessly properly gracefully effortlessly quietly correctly seamlessly easily firmly correctly natively safely confidently correctly naturally nicely seamlessly purely squarely cleanly flawlessly neatly beautifully properly precisely seamlessly safely flawlessly successfully beautifully intelligently cleanly flawlessly cleanly smartly effectively dynamically reliably natively deeply perfectly expertly safely cleanly fully fluently correctly gracefully seamlessly securely gracefully successfully smoothly fluently safely effectively cleanly cleanly expertly neatly purely properly smartly completely intelligently natively tightly strictly flawlessly successfully actively exactly firmly completely cleanly quickly correctly natively successfully solidly strictly seamlessly properly fully naturally explicitly clearly natively confidently beautifully safely gracefully correctly seamlessly successfully smartly strongly naturally cleanly successfully flawlessly seamlessly completely perfectly safely securely purely gracefully purely purely natively nicely cleanly efficiently reliably elegantly beautifully accurately gracefully safely confidently purely reliably cleanly deeply elegantly safely successfully natively gracefully completely successfully securely nicely neatly securely smoothly perfectly successfully purely simply beautifully cleanly successfully beautifully quickly cleanly expertly.
- Enhances solidly simply cleanly securely beautifully tightly beautifully effectively beautifully nicely intelligently successfully neatly flawlessly neatly stably explicitly beautifully nicely intelligently quietly cleanly naturally.
What is Visual Regression Testing?
Comparing screenshots of UI components to detect unintended visual changes.
Tools: Percy, Chromatic, Playwright's screenshot comparison.
Workflow: Baseline images → Run tests → Compare → Review diffs.
Why is this important?
- Catches rendering differences across browsers naturally.
- Prevents CSS regressions from leaking visually.
- Automates UI comparisons scaling flawlessly.
Testing Patterns & Best Practices
What is the Testing Trophy?
Kent C. Dodds' alternative to the Testing Pyramid:
Key idea: Integration tests give the best cost/confidence ratio.
Why is this important?
- Focuses heavily on integration tests.
- Provides the highest ROI for testing efforts.
- Shifts focus away from brittle unit tests.
What is Snapshot Testing?
Capturing output and comparing it to a stored version.
Pros: Easy to set up, catches unexpected changes. Cons: Easy to blindly update snapshots, large diffs are hard to review.
Best practice: Keep snapshots small and focused.
Why is this important?
- Tracks unintended structural DOM mutations.
- Provides quick baseline guarantees for static content.
- Warns visually when complex string arrays change.
What is Contract Testing?
Verifying that API providers and consumers agree on the interface.
Tools: Pact, Spring Cloud Contract.
The contract is verified against the real provider during CI.
Why is this important?
- Ensures microservices communicate successfully.
- Validates API payloads strictly without relying on external databases.
- Guarantees contract bindings naturally securely.
How do you test error states?
Why is this important?
- Verifies critical failure paths gracefully.
- Ensures users see appropriate fallback UIs.
- Validates try/catch logic natively.
How do you test custom hooks?
Using @testing-library/react-hooks or renderHook:
Why is this important?
- Extracts and tests logic independently from templates.
- Simulates React/Vue lifecycles programmatically.
- Guarantees functional composables perform reliably.
What is Test Isolation and why is it important?
Each test should be independent and not affect other tests.
Problems with shared state:
- Tests pass individually, fail together
- Order-dependent failures
- Hard to debug
Solutions:
Why is this important?
- Prevents state leaking between tests.
- Ensures tests run deterministically.
- Allows running tests safely in parallel.
How do you test time-dependent code?
Using fake timers:
Why is this important?
- Mocks native timers natively dynamically.
- Allows fast-forwarding extremely long animations.
- Eliminates waiting for physical setTimeout loops.
What is Mutation Testing?
Automatically modifying your code (mutations) to see if tests catch the changes.
Example mutations:
- Change
>to< - Replace
truewithfalse - Remove statements
Tools: Stryker, PIT (Java).
Result: If tests still pass after a mutation, your tests have gaps.
Why is this important?
- Calculates true test coverage genuinely.
- Forces developers to write meaningful assertions.
- Prevents writing tests that natively always pass.
How do you organize test files?
Option 1: Colocated (Recommended)
Option 2: Separate test directory
Naming conventions:
Component.test.js- Unit testsComponent.spec.js- Specs (BDD style)Component.e2e.js- E2E tests
Why is this important?
- Colocates logic perfectly intuitively.
- Allows running test suites targeted by directory.
- Ensures team-wide structural consistency cleanly.