Docs
Module-20-Testing-Debugging
Module 20: Testing & Debugging
Master the art of writing reliable, testable code and efficiently debugging JavaScript applications.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β TESTING & DEBUGGING β β
β β β β
β β "Code without tests is broken by design." - Jacob Kaplan-Moss β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β TEST β β DEBUG β β PROFILE β β MONITOR β β
β β βββββββ β β βββββββ β β βββββββ β β βββββββ β β
β β Unit β β DevTools β β Memory β β Logs β β
β β Integrationβ β Breakpointsβ β CPU β β Errors β β
β β E2E β β Console β β Network β β Metrics β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Module Overview
This module transforms you from a developer who hopes code works into one who knows it works. Learn professional testing practices, master debugging tools, and build confidence in your code.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β THE TESTING MINDSET β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Without Tests: With Tests: β
β ββββββββββββββ βββββββββββ β
β β
β function add(a, b) { function add(a, b) { β
β return a + b; return a + b; β
β } } β
β // "I think it works" β
β test('adds numbers', () => { β
β expect(add(2, 3)).toBe(5); β
β expect(add(-1, 1)).toBe(0); β
β expect(add(0, 0)).toBe(0); β
β }); β
β // "I KNOW it works" β
β β
β Benefits: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
Catch bugs before production β β
β β β
Refactor with confidence β β
β β β
Document expected behavior β β
β β β
Faster development in the long run β β
β β β
Better code design (testable = modular) β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Module Structure
20.1 Unit Testing Fundamentals
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β UNIT TESTING BASICS β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β The AAA Pattern: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β
β β test('user can update their name', () => { β β
β β // ARRANGE - Set up the test data β β
β β const user = new User('Alice'); β β
β β β β
β β // ACT - Perform the action being tested β β
β β user.setName('Bob'); β β
β β β β
β β // ASSERT - Verify the expected outcome β β
β β expect(user.name).toBe('Bob'); β β
β β }); β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Test Doubles: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β
β β TYPE PURPOSE EXAMPLE β β
β β ββββ βββββββ βββββββ β β
β β Dummy Fill parameter slots () => {} β β
β β Stub Return canned values () => 42 β β
β β Spy Record interactions jest.fn() β β
β β Mock Verify expectations jest.mock('./module') β β
β β Fake Working implementation In-memory database β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- β’Testing principles - Why, what, and how to test
- β’Test structure - Arrange-Act-Assert pattern
- β’Test doubles - Mocks, stubs, spies, fakes
- β’Code coverage - Measuring test completeness
20.2 Testing with Jest
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β JEST FRAMEWORK β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Matchers Cheat Sheet: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β // Equality β β
β β expect(x).toBe(y) // Strict equality (===) β β
β β expect(x).toEqual(y) // Deep equality β β
β β expect(x).toStrictEqual(y) // Deep + undefined properties β β
β β β β
β β // Truthiness β β
β β expect(x).toBeTruthy() β β
β β expect(x).toBeFalsy() β β
β β expect(x).toBeNull() β β
β β expect(x).toBeUndefined() β β
β β expect(x).toBeDefined() β β
β β β β
β β // Numbers β β
β β expect(x).toBeGreaterThan(y) β β
β β expect(x).toBeLessThan(y) β β
β β expect(x).toBeCloseTo(y) // For floating point β β
β β β β
β β // Strings β β
β β expect(x).toMatch(/pattern/) β β
β β expect(x).toContain('substring') β β
β β β β
β β // Arrays/Iterables β β
β β expect(arr).toContain(item) β β
β β expect(arr).toHaveLength(n) β β
β β β β
β β // Objects β β
β β expect(obj).toHaveProperty('key', value) β β
β β expect(obj).toMatchObject(partialObj) β β
β β β β
β β // Exceptions β β
β β expect(() => fn()).toThrow() β β
β β expect(() => fn()).toThrow(ErrorType) β β
β β expect(() => fn()).toThrow('message') β β
β β β β
β β // Negation β β
β β expect(x).not.toBe(y) β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Async Testing: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β // With async/await β β
β β test('async test', async () => { β β
β β const data = await fetchData(); β β
β β expect(data).toBe('result'); β β
β β }); β β
β β β β
β β // With resolves/rejects β β
β β test('promise resolves', () => { β β
β β return expect(fetchData()).resolves.toBe('result'); β β
β β }); β β
β β β β
β β test('promise rejects', () => { β β
β β return expect(badFetch()).rejects.toThrow('error'); β β
β β }); β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- β’Jest configuration - Setup and customization
- β’Matchers and assertions - Complete matcher reference
- β’Async testing - Testing promises and async/await
- β’Mocking - Mock functions and modules
20.3 Testing DOM and Browser Code
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DOM TESTING β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Testing Library Philosophy: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β
β β "The more your tests resemble the way your software is used, β β
β β the more confidence they can give you." β β
β β β β
β β Query Priority (most to least preferred): β β
β β ββββββββββββββββββββββββββββββββββββββββ β β
β β 1. getByRole β Accessible to everyone β β
β β 2. getByLabelText β Form fields β β
β β 3. getByPlaceholderText β β
β β 4. getByText β Non-interactive elements β β
β β 5. getByDisplayValue β Current form values β β
β β 6. getByAltText β Images β β
β β 7. getByTitle β β
β β 8. getByTestId β Last resort β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Example: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β import { render, screen, fireEvent } from '@testing-library/dom'; β β
β β β β
β β test('button click updates text', () => { β β
β β // Render β β
β β render(`<button>Click me</button><span></span>`); β β
β β β β
β β // Query β β
β β const button = screen.getByRole('button', { name: /click me/i });β β
β β β β
β β // Interact β β
β β fireEvent.click(button); β β
β β β β
β β // Assert β β
β β expect(screen.getByText('Clicked!')).toBeInTheDocument(); β β
β β }); β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- β’DOM testing utilities - JSDOM, Testing Library
- β’Event simulation - Click, input, keyboard events
- β’Async UI updates - waitFor, findBy queries
- β’Component testing - Testing UI components
20.4 Debugging Techniques
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DEBUGGING TOOLKIT β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Console Methods: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β console.log(obj) // Basic output β β
β β console.dir(obj) // Interactive object tree β β
β β console.table(arr) // Tabular format β β
β β console.group('name') // Group related logs β β
β β console.groupEnd() β β
β β console.time('label') // Start timer β β
β β console.timeEnd('label') // End timer, show duration β β
β β console.trace() // Show call stack β β
β β console.assert(cond) // Log if condition is false β β
β β console.count('label') // Count invocations β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Breakpoint Types: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β
β β Line Breakpoint β Click line number in Sources panel β β
β β Conditional β Right-click β Add conditional breakpoint β β
β β Logpoint β Right-click β Add logpoint (no pause) β β
β β DOM Breakpoint β Elements β Right-click β Break on... β β
β β XHR Breakpoint β Sources β XHR Breakpoints β β
β β Event Breakpoint β Sources β Event Listener Breakpoints β β
β β Exception β Sources β Pause on exceptions β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Stepping Controls: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β
β β βΆ Resume β Continue until next breakpoint β β
β β ‡ Step Over β Execute current line, move to next β β
β β β€ Step Into β Enter function call β β
β β ‴ Step Out β Complete current function, return to caller β β
β β β² Restart β Restart the current call frame β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- β’Browser DevTools - Full feature mastery
- β’Console methods - Beyond console.log
- β’Breakpoints - Strategic debugging
- β’Performance profiling - Finding bottlenecks
20.5 Error Handling & Logging
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ERROR MANAGEMENT β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Error Handling Strategy: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β
β β User Action β β
β β β β β
β β βΌ β β
β β βββββββββββββββββββ β β
β β β Try Operation β β β
β β βββββββββββββββββββ β β
β β β β β
β β Success? βββββββΊ β Continue normal flow β β
β β β β β
β β βΌ Error β β
β β βββββββββββββββββββ β β
β β β Catch & Log β βββΊ Send to error tracking service β β
β β βββββββββββββββββββ β β
β β β β β
β β βΌ β β
β β βββββββββββββββββββ β β
β β β Can Recover? β βββΊ Try fallback / retry β β
β β βββββββββββββββββββ β β
β β β No β β
β β βΌ β β
β β βββββββββββββββββββ β β
β β β Graceful Error β βββΊ Show user-friendly message β β
β β β UI β β β
β β βββββββββββββββββββ β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Logging Levels: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β
β β ERROR βββββββββββββ Critical failures, needs attention β β
β β WARN βββββββββ Potential issues, degraded performance β β
β β INFO βββββ Normal operations, milestones β β
β β DEBUG βββ Detailed diagnostic information β β
β β TRACE β Very detailed execution trace β β
β β β β
β β Production: ERROR, WARN, (INFO) β β
β β Development: All levels β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- β’Structured error handling - Consistent patterns
- β’Logging strategies - Development vs production
- β’Error tracking - Sentry, LogRocket, etc.
- β’Production debugging - Source maps and monitoring
π― Learning Flow
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LEARNING PROGRESSION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Week 1: Unit Testing Fundamentals β
β βββ Understand why testing matters β
β βββ Learn the AAA pattern β
β βββ Practice with simple pure functions β
β βββ Understand test doubles concepts β
β β
β Week 2: Jest Mastery β
β βββ Set up Jest in a project β
β βββ Learn all common matchers β
β βββ Test async code β
β βββ Mock functions and modules β
β β
β Week 3: DOM and Integration Testing β
β βββ Set up Testing Library β
β βββ Test UI components β
β βββ Simulate user interactions β
β βββ Write integration tests β
β β
β Week 4: Debugging and Error Handling β
β βββ Master DevTools debugging β
β βββ Use advanced console methods β
β βββ Implement error tracking β
β βββ Build logging infrastructure β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
πΊ Testing Pyramid
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β THE TESTING PYRAMID β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββ β
β β± E2E β² β
β β± (Manual) β² β FEW: Slow, expensive β
β β±ββββββββββββββ² Simulate real user flows β
β β± Integration β² β
β β± (Automated) β² β SOME: Medium speed β
β β±ββββββββββββββββββββ² Multiple units together β
β β± Unit Tests β² β
β β± (Automated) β² β MANY: Fast, cheap β
β β±ββββββββββββββββββββββββββ² Single functions/modules β
β β
β Unit Tests: β
β βββ Test individual functions and classes β
β βββ Fast execution (milliseconds) β
β βββ Easy to write and maintain β
β βββ Run on every save/commit β
β β
β Integration Tests: β
β βββ Test how units work together β
β βββ May involve database, API mocks β
β βββ Slower than unit tests β
β βββ Run before merge/deploy β
β β
β E2E Tests: β
β βββ Test complete user flows β
β βββ Use real browsers (Cypress, Playwright) β
β βββ Slowest, most expensive β
β βββ Run before major releases β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Key Concepts
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TESTING TERMINOLOGY β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Term β Description β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β Unit Test β Tests a single unit (function/class) in isolation β
β Integration Test β Tests multiple units working together β
β E2E Test β Tests entire application flow end-to-end β
β Test Suite β Collection of related tests β
β Test Case β Single test verifying specific behavior β
β Test Runner β Tool that executes tests (Jest, Mocha) β
β Assertion β Statement verifying expected outcome β
β Fixture β Test data setup β
β Mock β Simulated object with programmable behavior β
β Stub β Mock that returns canned responses β
β Spy β Records function calls for verification β
β Coverage β Percentage of code executed by tests β
β Regression β Bug reintroduced in previously working code β
β TDD β Write tests before implementation β
β BDD β Tests written in behavioral language β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Prerequisites
- β’Strong understanding of JavaScript functions
- β’Familiarity with async/await
- β’Basic understanding of the DOM
- β’Experience with npm/package management
π Section Files
| Section | Topic | Key Files |
|---|---|---|
| 20.1 | Unit Testing Fundamentals | 01-testing-principles.js, 02-test-doubles.js |
| 20.2 | Testing with Jest | 01-matchers.js, 02-async-testing.js, 03-mocking.js |
| 20.3 | DOM Testing | 01-dom-queries.js, 02-event-testing.js |
| 20.4 | Debugging | 01-console-methods.js, 02-devtools-tips.js |
| 20.5 | Error Handling | 01-error-patterns.js, 02-logging.js |
β οΈ Common Pitfalls
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TESTING PITFALLS TO AVOID β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β β Testing implementation, not behavior β
β βββββββββββββββββββββββββββββββββββββββββ β
β // Bad: Tests internal state β
β expect(counter._count).toBe(1); β
β // Good: Tests behavior β
β expect(counter.getValue()).toBe(1); β
β β
β β Tests that depend on each other β
β ββββββββββββββββββββββββββββββββ β
β // Bad: Test B depends on Test A running first β
β // Good: Each test sets up its own data β
β β
β β Not testing edge cases β
β βββββββββββββββββββββββββββββ β
β // Bad: Only test the happy path β
β // Good: Test null, empty, boundaries, errors β
β β
β β Over-mocking β
β ββββββββββββββ β
β // Bad: Mock everything, test doesn't verify real behavior β
β // Good: Mock external dependencies, not the unit under test β
β β
β β Ignoring flaky tests β
β βββββββββββββββββββββββ β
β // Bad: "It usually passes, skip it" β
β // Good: Fix timing issues, make tests deterministic β
β β
β β 100% coverage as a goal β
β βββββββββββββββββββββββββ β
β // Bad: Write pointless tests just to hit coverage β
β // Good: Focus on critical paths and edge cases β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Related Modules
- β’Previous: Module 19 - Advanced DOM & Browser APIs
- β’Next: Module 21 - Security Best Practices
- β’Related: Module 04 - Control Flow (try-catch)
π― Quick Reference
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β JEST QUICK REFERENCE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β // Test structure β
β describe('Module', () => { β
β beforeEach(() => { /* setup */ }); β
β afterEach(() => { /* cleanup */ }); β
β β
β test('should do something', () => { β
β expect(result).toBe(expected); β
β }); β
β β
β test.skip('skipped test', () => {}); β
β test.only('only this runs', () => {}); β
β }); β
β β
β // Common matchers β
β expect(x).toBe(y) // === β
β expect(x).toEqual(y) // Deep equal β
β expect(x).toBeTruthy() // Boolean true β
β expect(x).toContain(item) // Array/string contains β
β expect(fn).toThrow() // Function throws β
β expect(fn).toHaveBeenCalled() // Mock was called β
β expect(fn).toHaveBeenCalledWith() // Mock called with args β
β β
β // Mocking β
β jest.fn() // Create mock function β
β jest.mock('./module') // Mock entire module β
β jest.spyOn(obj, 'method') // Spy on existing method β
β β
β // Async β
β await expect(p).resolves.toBe(x) // Promise resolves β
β await expect(p).rejects.toThrow() // Promise rejects β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ