Modern software testing requires more than just manual clicking and exploratory testing. Today’s QA engineers need powerful development environments, specialized extensions, and debugging tools to write automated tests, analyze network traffic, and investigate bugs efficiently. This comprehensive guide covers the essential IDEs, extensions, and tools that every tester should master.

Table of Contents

  1. VS Code for QA Engineers
  2. IntelliJ IDEA for Testing
  3. Browser DevTools Mastery
  4. Proxy Tools: Charles and Fiddler
  5. Choosing the Right Tools

VS Code for QA Engineers

Visual Studio Code has become the go-to editor for many testers due to its lightweight nature, extensive extension marketplace, and excellent support for multiple programming languages. Let’s explore how to transform VS Code into a powerful testing environment.

Essential Extensions for Testers

1. Test Runner Extensions

Jest Runner

  • Direct integration with Jest testing framework
  • Run individual tests or test suites with one click
  • Display test results inline in the editor
  • Debug tests directly from the editor

Installation:

code --install-extension Orta.vscode-jest

Configuration in .vscode/settings.json:

{
  "jest.autoRun": "off",
  "jest (as discussed in [From Manual to Automation: Complete Transition Guide for QA Engineers](/blog/manual-to-automation-transition)).showCoverageOnLoad": true,
  "jest.coverageFormatter": "DefaultFormatter",
  "jest.debugMode": true
}

Test Explorer UI

  • Unified test explorer for multiple frameworks
  • Supports Jest, Mocha, Pytest, JUnit, and more
  • Tree view of all tests with pass/fail indicators
  • Quick navigation to test definitions
code --install-extension hbenl.vscode-test-explorer

Playwright Test for VSCode

  • Run Playwright tests directly from VS Code
  • Pick locators with visual selector tool
  • Record tests with codegen integration
  • Debug with breakpoints
code --install-extension ms-playwright.playwright

Configuration example:

{
  "playwright.reuseBrowser": true,
  "playwright (as discussed in [Cloud Testing Platforms: Complete Guide to BrowserStack, Sauce Labs, AWS Device Farm & More](/blog/cloud-testing-platforms)).showTrace": true,
  "playwright.env": {
    "HEADLESS": "false"
  }
}

2. Code Quality and Linting

ESLint Essential for JavaScript/TypeScript test code quality:

code --install-extension dbaeumer.vscode-eslint

.eslintrc.js for test files:

module.exports = {
  env: {
    node: true,
    jest: true,
    mocha: true
  },
  extends: [
    'eslint:recommended',
    'plugin:jest/recommended'
  ],
  rules: {
    'jest/no-disabled-tests': 'warn',
    'jest/no-focused-tests': 'error',
    'jest/valid-expect': 'error'
  }
}

Prettier Consistent code formatting for test automation:

code --install-extension esbenp.prettier-vscode

Configuration:

{
  "editor.formatOnSave": true,
  "prettier.singleQuote": true,
  "prettier.semi": false,
  "prettier.tabWidth": 2
}

3. API Testing Extensions

REST Client Test API endpoints without leaving VS Code:

code --install-extension humao.rest-client

Create .http files for API testing:

### Get User by ID
GET https://api.example.com/users/123
Authorization: Bearer {{token}}

### Create New User
POST https://api.example.com/users
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john@example.com"
}

### Variables
@baseUrl = https://api.example.com
@token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

### Using Variables
GET {{baseUrl}}/profile
Authorization: Bearer {{token}}

Thunder Client Lightweight alternative to Postman:

code --install-extension rangav.vscode-thunder-client

Features:

  • Collections and environments
  • Graphical interface for API testing
  • Generate code snippets in multiple languages
  • Import/export Postman collections

4. Debugging and Inspection

JavaScript Debugger Built into VS Code, but requires configuration:

Create .vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Jest Current File",
      "program": "${workspaceFolder}/node_modules/.bin/jest",
      "args": [
        "${fileBasename}",
        "--runInBand",
        "--no-cache"
      ],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen"
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Playwright Test",
      "program": "${workspaceFolder}/node_modules/.bin/playwright",
      "args": [
        "test",
        "${file}",
        "--debug"
      ],
      "console": "integratedTerminal"
    }
  ]
}

CodeLLDB (for Python testing):

code --install-extension vadimcn.vscode-lldb

Python debugging configuration:

{
  "type": "python",
  "request": "launch",
  "name": "Pytest Current File",
  "module": "pytest",
  "args": [
    "${file}",
    "-v",
    "-s"
  ],
  "console": "integratedTerminal"
}

5. Version Control and Collaboration

GitLens Enhanced Git capabilities for tracking test changes:

code --install-extension eamodio.gitlens

Key features for testers:

  • Blame annotations showing who wrote each test
  • File history to track test evolution
  • Compare test versions across branches
  • Line history for understanding test modifications

Live Share Pair testing and collaborative debugging:

code --install-extension MS-vsliveshare.vsliveshare

Use cases:

  • Pair programming on test automation
  • Remote debugging sessions
  • Collaborative test review
  • Knowledge sharing sessions

Custom Snippets for Test Automation

Create custom snippets in Code > Preferences > User Snippets:

Jest Test Snippets (javascript.json):

{
  "Jest Describe Block": {
    "prefix": "desc",
    "body": [
      "describe('${1:suite name}', () => {",
      "  ${2:// test code}",
      "});"
    ]
  },
  "Jest Test Case": {
    "prefix": "test",
    "body": [
      "test('${1:test name}', async () => {",
      "  ${2:// test implementation}",
      "});"
    ]
  },
  "Jest Before Each": {
    "prefix": "beforeach",
    "body": [
      "beforeEach(async () => {",
      "  ${1:// setup code}",
      "});"
    ]
  },
  "API Test Template": {
    "prefix": "apitest",
    "body": [
      "test('${1:endpoint} should ${2:expected behavior}', async () => {",
      "  const response = await request(app)",
      "    .${3:get}('${4:/api/endpoint}')",
      "    .set('Authorization', `Bearer \\${token}`);",
      "",
      "  expect(response.status).toBe(${5:200});",
      "  expect(response.body).toMatchObject({",
      "    ${6:// expected properties}",
      "  });",
      "});"
    ]
  }
}

Playwright Snippets:

{
  "Playwright Test": {
    "prefix": "pwtest",
    "body": [
      "test('${1:test description}', async ({ page }) => {",
      "  await page.goto('${2:https://example.com}');",
      "  ${3:// test steps}",
      "});"
    ]
  },
  "Playwright Expect": {
    "prefix": "pwexpect",
    "body": [
      "await expect(page.locator('${1:selector}')).${2:toBeVisible}();"
    ]
  }
}

Workspace Configuration for Test Projects

Create .vscode/settings.json for your test project:

{
  "files.exclude": {
    "**/.git": true,
    "**/node_modules": true,
    "**/coverage": true,
    "**/playwright-report": true
  },
  "search.exclude": {
    "**/node_modules": true,
    "**/coverage": true,
    "**/dist": true
  },
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "files.associations": {
    "*.spec.js": "javascript",
    "*.test.js": "javascript",
    "*.http": "http"
  },
  "jest.autoRun": {
    "watch": false,
    "onSave": "test-file"
  },
  "testing.automaticallyOpenPeekView": "failureInVisibleDocument",
  "terminal.integrated.defaultProfile.osx": "zsh",
  "npm.enableScriptExplorer": true
}

Tasks for Common Testing Operations

Create .vscode/tasks.json:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Run All Tests",
      "type": "npm",
      "script": "test",
      "problemMatcher": [],
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    },
    {
      "label": "Run Tests with Coverage",
      "type": "npm",
      "script": "test:coverage",
      "problemMatcher": [],
      "presentation": {
        "reveal": "always"
      }
    },
    {
      "label": "Lint Test Files",
      "type": "npm",
      "script": "lint",
      "problemMatcher": ["$eslint-stylish"]
    },
    {
      "label": "Generate Playwright Report",
      "type": "shell",
      "command": "npx playwright show-report",
      "problemMatcher": []
    }
  ]
}

Keyboard Shortcuts for Productivity

Customize keyboard shortcuts in Keybindings (JSON):

[
  {
    "key": "ctrl+shift+t",
    "command": "testing.runCurrentFile"
  },
  {
    "key": "ctrl+shift+d",
    "command": "testing.debugCurrentFile"
  },
  {
    "key": "ctrl+shift+a",
    "command": "testing.runAll"
  },
  {
    "key": "ctrl+shift+f",
    "command": "testing.reRunFailTests"
  }
]

Multi-Root Workspaces for Complex Projects

For projects with separate frontend and backend tests:

Create test-automation.code-workspace:

{
  "folders": [
    {
      "name": "API Tests",
      "path": "./api-tests"
    },
    {
      "name": "E2E Tests",
      "path": "./e2e-tests"
    },
    {
      "name": "Performance Tests",
      "path": "./performance-tests"
    }
  ],
  "settings": {
    "files.watcherExclude": {
      "**/node_modules/**": true
    }
  }
}

IntelliJ IDEA for Testing

IntelliJ IDEA (and other JetBrains IDEs) provide powerful features for Java-based test automation, including excellent support for JUnit, TestNG, Selenium, and other testing frameworks.

Essential Plugins for Testing

1. Test Automation Plugins

JUnit 5 Support (Built-in)

  • Run tests from editor gutter icons
  • Navigate between tests and production code
  • Generate test methods automatically
  • Coverage analysis

Configuration in Run Configuration:

VM options: -ea -Dfile.encoding=UTF-8
Working directory: $MODULE_WORKING_DIR$
Environment variables: ENV=test

TestNG Plugin Advanced testing framework support:

<!-- pom.xml dependency -->
<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>7.8.0</version>
    <scope>test</scope>
</dependency>

TestNG configuration (testng.xml):

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Test Suite" parallel="methods" thread-count="5">
    <test name="API Tests">
        <classes>
            <class name="com.example.tests.UserApiTest"/>
            <class name="com.example.tests.ProductApiTest"/>
        </classes>
    </test>
    <test name="UI Tests">
        <packages>
            <package name="com.example.tests.ui"/>
        </packages>
    </test>
</suite>

Cucumber for Java BDD testing support:

Settings > Plugins > Install "Cucumber for Java"

Features:

  • Gherkin syntax highlighting
  • Navigation from steps to step definitions
  • Generate step definitions from feature files
  • Run scenarios from editor

Example feature file:

Feature: User Authentication

  Background:
    Given the application is running
    And the database is clean

  @smoke @api
  Scenario: Successful login with valid credentials
    Given a user with username "testuser" exists
    When the user logs in with username "testuser" and password "Test123!"
    Then the login should be successful
    And a valid JWT token should be returned

  @negative
  Scenario Outline: Failed login attempts
    When the user logs in with username "<username>" and password "<password>"
    Then the login should fail
    And the error message should be "<error>"

    Examples:
      | username  | password  | error                   |
      | invalid   | Test123!  | Invalid credentials     |
      | testuser  | wrong     | Invalid credentials     |
      |           | Test123!  | Username required       |

2. Code Coverage Tools

IntelliJ IDEA Code Coverage (Built-in) Run tests with coverage:

  1. Right-click on test class/package
  2. Select “Run with Coverage”
  3. View coverage in editor gutter and Coverage tool window

Configuration in .idea/workspace.xml:

<component name="CoverageOptionsProvider">
  <option name="myAddOrReplace" value="2" />
  <option name="myGlobalRunner" value="IDEA" />
  <option name="myTraceTestFramework" value="false" />
</component>

JaCoCo Plugin More advanced coverage reporting:

<!-- Maven plugin -->
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.11</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
        <execution>
            <id>jacoco-check</id>
            <goals>
                <goal>check</goal>
            </goals>
            <configuration>
                <rules>
                    <rule>
                        <element>PACKAGE</element>
                        <limits>
                            <limit>
                                <counter>LINE</counter>
                                <value>COVEREDRATIO</value>
                                <minimum>0.80</minimum>
                            </limit>
                        </limits>
                    </rule>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

3. REST API Testing

HTTP Client (Built-in) Create .http files for API testing:

### Development environment
@host = http://localhost:8080
@token = {{auth_token}}

### Get Authentication Token
# @name auth
POST {{host}}/api/auth/login
Content-Type: application/json

{
  "username": "admin",
  "password": "admin123"
}

> {% client.global.set("auth_token", response.body.token); %}

### Get All Users (Authenticated)
GET {{host}}/api/users
Authorization: Bearer {{token}}

### Create New User
POST {{host}}/api/users
Content-Type: application/json
Authorization: Bearer {{token}}

{
  "username": "newuser",
  "email": "newuser@example.com",
  "role": "USER"
}

### Update User
# @name updateUser
PUT {{host}}/api/users/{{userId}}
Content-Type: application/json
Authorization: Bearer {{token}}

{
  "email": "updated@example.com"
}

### Response handler
> {%
    client.test("Request executed successfully", function() {
        client.assert(response.status === 200, "Response status is not 200");
    });

    client.test("User updated correctly", function() {
        client.assert(response.body.email === "updated@example.com");
    });
%}

### Delete User
DELETE {{host}}/api/users/{{userId}}
Authorization: Bearer {{token}}

4. Database Tools Integration

Database Tools and SQL (Built-in) Connect to test databases for data verification:

  1. Open Database tool window
  2. Add data source (PostgreSQL, MySQL, etc.)
  3. Create SQL console for test data management

Example test data setup script:

-- Setup test data
TRUNCATE TABLE users CASCADE;
TRUNCATE TABLE orders CASCADE;

INSERT INTO users (id, username, email, role, created_at)
VALUES
    (1, 'testuser1', 'test1@example.com', 'USER', NOW()),
    (2, 'testuser2', 'test2@example.com', 'USER', NOW()),
    (3, 'admin', 'admin@example.com', 'ADMIN', NOW());

INSERT INTO orders (id, user_id, product_id, quantity, total, status)
VALUES
    (1, 1, 101, 2, 199.98, 'COMPLETED'),
    (2, 1, 102, 1, 49.99, 'PENDING'),
    (3, 2, 101, 1, 99.99, 'COMPLETED');

-- Verify data
SELECT u.username, COUNT(o.id) as order_count, SUM(o.total) as total_spent
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.username;

Live Templates for Test Code

Create custom live templates in Settings > Editor > Live Templates:

JUnit 5 Test Method:

@Test
@DisplayName("$DESCRIPTION$")
void $METHOD_NAME$() {
    // Arrange
    $ARRANGE$
    
    // Act
    $ACT$
    
    // Assert
    $ASSERT$
}

REST Assured API Test:

@Test
void test$METHOD$Returns$STATUS$() {
    given()
        .contentType(ContentType.JSON)
        .header("Authorization", "Bearer " + token)
        .when()
        .$HTTP_METHOD$("$ENDPOINT$")
        .then()
        .statusCode($STATUS_CODE$)
        .body("$JSON_PATH$", equalTo($EXPECTED_VALUE$));
}

Selenium Page Object Method:

public $RETURN_TYPE$ $METHOD_NAME$($PARAMETERS$) {
    wait.until(ExpectedConditions.elementToBeClickable($ELEMENT$));
    $ELEMENT$.$ACTION$();
    return $RETURN_VALUE$;
}

TestNG Data Provider:

@DataProvider(name = "$PROVIDER_NAME$")
public Object[][] $METHOD_NAME$() {
    return new Object[][] {
        $DATA$
    };
}

Run Configurations for Test Execution

JUnit Run Configuration Template:

Name: All Unit Tests
Test kind: All in package
Package: com.example.tests.unit
VM options: -ea -Xmx512m
Working directory: $MODULE_DIR$
Environment variables: 
  ENV=test
  LOG_LEVEL=DEBUG
Before launch: Build, Run Maven Goal (clean compile)

TestNG Suite Configuration:

Name: Integration Tests
Suite: src/test/resources/testng-integration.xml
VM options: -Denv=staging -Dbrowser=chrome
Listeners: com.example.listeners.TestListener
Before launch: Build, Run Maven Goal (clean test-compile)

Debugging Test Failures

Conditional Breakpoints: Right-click on breakpoint and add condition:

username.equals("problematicUser") && response.getStatus() != 200

Evaluate Expression: During debugging, use Alt+F8 to evaluate:

// Check JSON response content
new ObjectMapper().readTree(response.getBody().asString())

// Verify element state
driver.findElement(By.id("submitBtn")).isEnabled()

// Database query verification
jdbcTemplate.queryForObject("SELECT COUNT(*) FROM users WHERE status = 'ACTIVE'", Integer.class)

Exception Breakpoints: Set breakpoints for specific exceptions:

  • Go to Run > View Breakpoints
  • Add Java Exception Breakpoints
  • Enter exception class (e.g., AssertionError, TimeoutException)

Code Analysis and Inspection

Enable useful inspections for test code:

Settings > Editor > Inspections > Enable:
- JUnit > Test method naming convention
- JUnit > Test method without assertions
- TestNG > Dependent methods
- Java > Probable bugs > Constant conditions
- Java > Testing > Assertion arguments order

Custom inspection profile for tests:

<!-- .idea/inspectionProfiles/Tests.xml -->
<profile version="1.0">
  <option name="myName" value="Tests" />
  <inspection_tool class="JUnitTestMethodWithNoAssertions" enabled="true" level="WARNING" />
  <inspection_tool class="TestMethodWithoutAssertion" enabled="true" level="WARNING" />
</profile>

Browser DevTools Mastery

Browser Developer Tools are essential for every tester, whether you’re debugging UI issues, analyzing network performance, or investigating JavaScript errors. Modern browsers (Chrome, Firefox, Safari, Edge) offer powerful built-in tools.

Chrome DevTools for Testing

1. Elements Panel

Inspecting DOM for Test Automation:

  • Right-click element → Inspect
  • Find unique selectors for automation
  • Copy XPath: Right-click element → Copy → Copy XPath
  • Copy JS Path: Right-click element → Copy → Copy JS path

Best Practices for Selector Generation:

// Instead of fragile XPath:
// /html/body/div[1]/div[2]/form/div[3]/button

// Use more stable selectors:
document.querySelector('[data-testid="submit-button"]')
document.querySelector('button[type="submit"].primary')

// Or relative XPath:
//button[contains(text(), 'Submit')]
//button[@data-testid='submit-button']

Live Edit for Testing:

  • Double-click attributes to modify
  • Edit as HTML for complex changes
  • Test CSS changes in Styles panel
  • Force element states: :hover, :active, :focus

2. Console Panel

Essential Console Commands for Testers:

// Query elements (similar to test automation)
$('button.submit')           // Returns first match (like querySelector)
$$('button')                 // Returns all matches (like querySelectorAll)
$x('//button[@type="submit"]') // XPath query

// Inspect elements
inspect($('button.submit'))  // Opens Elements panel

// Monitor events
monitorEvents($('form'), 'submit')  // Log form submission
unmonitorEvents($('form'))          // Stop monitoring

// Network monitoring
monitor(functionName)        // Log when function is called
unmonitor(functionName)

// Performance
console.time('operationName')
// ... code execution ...
console.timeEnd('operationName')  // Shows execution time

// Table display for data analysis
console.table(users)         // Display array of objects as table

// Test assertions
console.assert(value > 0, 'Value must be positive')

// Get event listeners
getEventListeners($('button.submit'))

// Copy data to clipboard
copy(JSON.stringify(userData))

Snippets for Reusable Test Scripts:

Create snippet in Sources > Snippets:

// Snippet: Check All Validation Errors
(function checkValidation() {
  const errors = $$('.error-message');
  console.table(errors.map(el => ({
    element: el.closest('[data-testid]')?.dataset.testid || 'unknown',
    message: el.textContent.trim(),
    visible: window.getComputedStyle(el).display !== 'none'
  })));
})();

// Snippet: Test Form Data
(function getFormData() {
  const form = $('form');
  const formData = new FormData(form);
  const data = {};
  for (let [key, value] of formData.entries()) {
    data[key] = value;
  }
  console.log('Form Data:', data);
  copy(JSON.stringify(data, null, 2));
  console.log('Copied to clipboard!');
})();

// Snippet: Find Orphaned Test IDs
(function findOrphanedTestIds() {
  const elements = $$('[data-testid]');
  const testIds = elements.map(el => ({
    id: el.dataset.testid,
    tag: el.tagName,
    text: el.textContent.trim().substring(0, 50)
  }));
  
  console.table(testIds);
  console.log(`Total: ${testIds.length} elements with test IDs`);
})();

3. Network Panel

Analyzing API Requests for Testing:

Filtering Requests:

Filter by type: XHR, Fetch, JS, CSS, Img
Filter by domain: domain:api.example.com
Filter by status: status-code:404
Filter by method: method:POST
Combine: method:POST domain:api status-code:200

Request Analysis:

  • Headers: Check authorization tokens, content types
  • Payload: Verify request body format
  • Preview: View response data structure
  • Response: Raw response data
  • Timing: Analyze request duration

Copy Request as Code: Right-click request → Copy → Copy as cURL / Copy as fetch / Copy as PowerShell

# Example cURL for test automation
curl 'https://api.example.com/users' \
  -H 'Authorization: Bearer eyJhbGc...' \
  -H 'Content-Type: application/json' \
  --data-raw '{"username":"testuser"}' \
  --compressed

HAR File Export for Bug Reports:

  1. Right-click in Network panel
  2. Save all as HAR
  3. Attach to bug report for complete network trace

Throttling for Performance Testing:

Network panel > Throttling dropdown:
- Fast 3G (1.6 Mbps)
- Slow 3G (400 Kbps)
- Offline
- Custom profiles

4. Sources Panel for Debugging

JavaScript Debugging for Testers:

Breakpoint Types:

  1. Line Breakpoints: Click line number
  2. Conditional Breakpoints: Right-click line → Add conditional breakpoint
    userId === 123 && response.status !== 200
    
  3. DOM Breakpoints: Right-click element in Elements panel
    • Break on subtree modifications
    • Break on attribute modifications
    • Break on node removal
  4. Event Listener Breakpoints: Sources > Event Listener Breakpoints
    • Mouse > click
    • Keyboard > keydown
    • Form > submit
    • XHR > XMLHttpRequest sent
  5. XHR/Fetch Breakpoints: Sources > XHR/fetch Breakpoints
    • Add URL pattern: api/users

Local Overrides for Testing:

1. Sources > Overrides > Enable Local Overrides
2. Select folder for overrides
3. Edit response in Sources panel
4. Save (Ctrl+S)
5. Reload page to test modified response

Use cases:

  • Test error handling without backend changes
  • Modify API responses for edge cases
  • Test different data scenarios
  • Simulate slow/failed responses

Blackboxing Third-Party Scripts:

Settings > Blackboxing > Add pattern
Pattern: node_modules/

Improves debugging by skipping library code.

5. Performance Panel

Recording Performance for Test Analysis:

1. Click Record
2. Perform actions
3. Stop recording
4. Analyze:
   - FPS: Frames per second (smooth = 60 FPS)
   - CPU: JavaScript execution time
   - Network: Request waterfall
   - Screenshots: Visual timeline

Key Metrics for Testers:

  • FCP (First Contentful Paint): When first content appears
  • LCP (Largest Contentful Paint): When main content loaded
  • TTI (Time to Interactive): When page becomes interactive
  • TBT (Total Blocking Time): Time main thread is blocked
  • CLS (Cumulative Layout Shift): Visual stability

Performance Testing Script:

// Record performance metrics
const perfData = performance.getEntriesByType('navigation')[0];
console.table({
  'DNS Lookup': perfData.domainLookupEnd - perfData.domainLookupStart,
  'TCP Connection': perfData.connectEnd - perfData.connectStart,
  'Request Time': perfData.responseStart - perfData.requestStart,
  'Response Time': perfData.responseEnd - perfData.responseStart,
  'DOM Processing': perfData.domInteractive - perfData.responseEnd,
  'Total Load Time': perfData.loadEventEnd - perfData.navigationStart
});

// Get Web Vitals
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(`${entry.name}: ${entry.value}`);
  }
});
observer.observe({ entryTypes: ['largest-contentful-paint', 'first-input', 'layout-shift'] });

6. Application Panel

Storage Inspection for Testing:

Local Storage / Session Storage:

// View in Console
console.table(Object.entries(localStorage))

// Test data manipulation
localStorage.setItem('authToken', 'test-token-123')
localStorage.removeItem('userId')
localStorage.clear()

// Test for automation
expect(localStorage (as discussed in [Test Management Systems: Jira vs TestRail vs Zephyr](/blog/test-management-systems-comparison)).getItem('theme')).toBe('dark')

Cookies:

  • View all cookies for domain
  • Edit cookie values
  • Delete individual cookies
  • Clear all cookies

IndexedDB:

  • Inspect database structure
  • View stored records
  • Delete databases for clean test state

Cache Storage:

  • Inspect Service Worker caches
  • View cached responses
  • Delete cache for testing

7. Lighthouse for Quality Testing

Run automated audits:

1. Open Lighthouse panel
2. Select categories:
   - Performance
   - Accessibility
   - Best Practices
   - SEO
   - Progressive Web App
3. Choose device (Mobile/Desktop)
4. Click "Generate report"

Command Line Lighthouse:

npm install -g lighthouse

# Run audit
lighthouse https://example.com --output html --output-path ./report.html

# With custom config
lighthouse https://example.com \
  --throttling.cpuSlowdownMultiplier=4 \
  --only-categories=performance,accessibility \
  --chrome-flags="--headless"

Firefox Developer Tools

Unique Features for Testers:

CSS Grid/Flexbox Inspector:

  • Visual overlay for Grid/Flexbox layouts
  • Better than Chrome for CSS debugging

Accessibility Inspector:

Tools > Browser Tools > Accessibility
- View accessibility tree
- Check ARIA attributes
- Simulate color blindness
- Check contrast ratios

Screenshot Command:

Open Developer Tools > Settings (F1) > Available Toolbox Buttons > Enable "Take a screenshot"

Or use Console:
:screenshot --fullpage
:screenshot --selector ".main-content"

Network Request Blocking:

Network panel > Right-click request > Block URL

Test error handling without backend changes.


Proxy Tools: Charles and Fiddler

Proxy tools intercept HTTP/HTTPS traffic between client and server, enabling testers to inspect, modify, and mock API responses. Essential for mobile testing, API testing, and security testing.

Charles Proxy

Charles is a cross-platform HTTP proxy / HTTP monitor / Reverse Proxy that enables developers and testers to view all HTTP/HTTPS traffic.

Installation and Setup

# macOS
brew install --cask charles

# Windows: Download from charlesproxy.com
# License: ~$50 (free trial available)

Initial Configuration:

  1. Proxy > Proxy Settings
    • Port: 8888 (default)
    • Enable transparent HTTP proxying: ✓
  2. Proxy > macOS Proxy (to set system proxy)

SSL Certificate Installation (for HTTPS decryption):

macOS:

1. Help > SSL Proxying > Install Charles Root Certificate
2. Open Keychain Access
3. Find "Charles Proxy" certificate
4. Double-click > Trust > Always Trust

Windows:

1. Help > SSL Proxying > Install Charles Root Certificate
2. Certificate will be added to Windows Certificate Store

Mobile Device (iOS/Android):

1. Connect device to same WiFi as computer
2. Device WiFi Settings > Configure Proxy > Manual
   - Server: [Computer IP]
   - Port: 8888
3. Open browser on device: chls.pro/ssl
4. Install certificate
5. iOS: Settings > General > About > Certificate Trust Settings > Enable

SSL Proxying Settings

Enable SSL proxying for specific hosts:

Proxy > SSL Proxying Settings > Add

Location:
  Host: *.example.com
  Port: 443

Or for all hosts:
  Host: *
  Port: 443

Recording and Analyzing Traffic

Structure View:

  • Hierarchical view of hosts and paths
  • Expand to see all requests to specific endpoint
  • Right-click > Clear to remove noise

Sequence View:

  • Chronological list of all requests
  • Better for understanding request flow
  • Shows exact timing of requests

Request/Response Inspector:

Tabs:

  • Overview: Method, status, timing, size
  • Headers: Request/response headers
  • Text: Plain text response
  • JSON: Formatted JSON with tree view
  • XML: Formatted XML
  • Raw: Complete raw request/response

Traffic Filtering

Focus on Specific Host:

Right-click host > Focus
Now only shows traffic for that host

Recording Settings:

Proxy > Recording Settings > Include

Add:
  Protocol: HTTP+HTTPS
  Host: api.example.com
  Port: 443
  Path: /api/*

Filter by Content Type:

View > Filter Settings

Show only:
☑ JSON
☑ XML
☐ HTML
☐ Images
☐ CSS/JavaScript

Request Manipulation

Breakpoints for Request/Response Modification:

1. Proxy > Breakpoint Settings > Enable Breakpoints
2. Add breakpoint:
   - Host: api.example.com
   - Path: /api/users
   - Request: ✓
   - Response: ✓

When request/response hits breakpoint:

  • Edit JSON Request tab: Modify request body
  • Edit Response tab: Modify response
  • Click Execute to continue

Use Cases:

  • Test error handling by changing status codes
  • Modify response data for edge cases
  • Change request parameters
  • Test timeout scenarios (add delay)

Map Local & Map Remote

Map Local (Replace remote response with local file):

Tools > Map Local Settings > Add

Map From:
  Protocol: HTTPS
  Host: api.example.com
  Path: /api/users
  
Map To:
  Local Path: /Users/test/mock-responses/users.json

Mock response file (users.json):

{
  "users": [
    {
      "id": 1,
      "name": "Test User",
      "email": "test@example.com",
      "role": "admin"
    }
  ],
  "total": 1
}

Map Remote (Redirect requests to different server):

Tools > Map Remote Settings > Add

Map From:
  Protocol: HTTPS
  Host: api-prod.example.com
  Path: /api/v2/users

Map To:
  Protocol: HTTPS
  Host: api-staging.example.com
  Path: /api/v2/users

Use cases:

  • Test against staging while using production frontend
  • Test new API version
  • Test load balancer behavior

Rewrite Tool

Modify Requests/Responses with Rules:

Tools > Rewrite Settings > Add

Name: Add CORS Headers
Apply to: api.example.com

Add Rule:
  Type: Add Header
  Where: Response
  Name: Access-Control-Allow-Origin
  Value: *

Add Rule:
  Type: Modify Status
  Where: Response
  Status: 200
  (Change 4xx/5xx to 200 for testing)

Add Rule:
  Type: Body Replacement
  Where: Response
  Match: "status":"active"
  Replace: "status":"inactive"

Throttling (Network Conditioning)

Proxy > Throttle Settings > Enable Throttling

Preset: 3G (780 kbps down, 330 kbps up)
Or Custom:
  Bandwidth: 512 kbps
  Utilisation: 80%
  Round-trip latency: 300ms
  MTU: 1500 bytes

Apply to: Only selected hosts
Add: api.example.com

Use Cases:

  • Test app behavior on slow networks
  • Test timeouts
  • Test loading states
  • Test progressive enhancement

Repeat Requests

Repeat Testing:

Right-click request > Repeat
Right-click request > Repeat Advanced
  - Count: 10
  - Concurrency: 5
  - Delay: 1000ms

Use for:

  • Load testing (basic)
  • Testing race conditions
  • Testing rate limiting
  • Reproducing intermittent issues

Export and Reporting

Export Session:

File > Export Session
Formats:
  - Charles Session (.chls)
  - HAR (HTTP Archive)
  - CSV
  - JSON

Generate Report:

File > Export Report
  - HTML Report
  - Include request/response bodies
  - Include timing information

Attach to bug reports for complete context.

Fiddler Classic / Fiddler Everywhere

Fiddler is another powerful web debugging proxy, popular on Windows. Fiddler Everywhere is the cross-platform version.

Installation

# Windows (Fiddler Classic - Free)
winget install Fiddler.Fiddler

# Cross-platform (Fiddler Everywhere - Subscription)
# Download from telerik.com/fiddler

Key Features

Composers: Create custom requests:

Composer > Parsed

Request:
  Method: POST
  URL: https://api.example.com/users
  Headers:
    Content-Type: application/json
    Authorization: Bearer {token}
  Body:
    {
      "username": "testuser",
      "email": "test@example.com"
    }

Execute > View response

AutoResponder (Similar to Charles Map Local):

Rules > Add Rule

If request matches:
  EXACT: https://api.example.com/users
Then respond with:
  File: C:\mocks\users.json
  Or: *404
  Or: *delay:5000 (5 second delay)
  Or: *bpu (break on request)

FiddlerScript (C# scripting):

// Auto-modify requests
static function OnBeforeRequest(oSession: Session) {
    // Add header to all API requests
    if (oSession.uriContains("/api/")) {
        oSession.oRequest["X-Test-Mode"] = "true";
    }
    
    // Block analytics
    if (oSession.uriContains("analytics.google.com")) {
        oSession.oRequest.FailSession(404, "Blocked", "");
    }
}

// Auto-modify responses
static function OnBeforeResponse(oSession: Session) {
    // Force CORS
    if (oSession.uriContains("/api/")) {
        oSession.oResponse["Access-Control-Allow-Origin"] = "*";
    }
    
    // Log slow responses
    if (oSession.Timers.ClientDoneResponse.Subtract(oSession.Timers.ClientBeginRequest).TotalMilliseconds > 2000) {
        FiddlerObject.log("Slow request: " + oSession.fullUrl);
    }
}

Filters:

Filters tab:

Hosts:
  Show only: api.example.com
  Hide: cdn.example.com

Client Process:
  Show only: chrome.exe

Breakpoints:
  Break request on POST
  Break response on status 500

Request Builder: More advanced than Composer:

Request Builder > New Request

Templates:
  - REST API GET
  - REST API POST with JSON
  - SOAP Request
  - GraphQL Query

Save as collection for reuse

Comparing Charles vs Fiddler

FeatureCharlesFiddler ClassicFiddler Everywhere
PlatformMac, Windows, LinuxWindows onlyMac, Windows, Linux
Price$50 (perpetual)Free$150/year subscription
UINative (Java Swing)Native (WinForms)Electron (modern)
Learning CurveMediumMediumEasy
PerformanceGoodExcellentGood
ScriptingLimitedC# (powerful)JavaScript
SSL SetupEasyEasyEasiest
Mobile TestingExcellentExcellentExcellent
Request MockingMap Local/RemoteAutoResponderMock Server
Network ThrottlingYesYesYes
API TestingBasicComposerAdvanced (collections)
Best ForMac users, simplicityWindows power usersTeams, cross-platform

Mobile Testing Workflow

Complete mobile testing setup:

  1. Configure Proxy on Device:
iOS:
  Settings > Wi-Fi > [Network] > Configure Proxy
  Manual: [Computer IP]:8888

Android:
  Settings > Wi-Fi > [Network] > Advanced
  Proxy: Manual
  Hostname: [Computer IP]
  Port: 8888
  1. Install SSL Certificate (see Charles setup above)

  2. Enable SSL Proxying for app domains

  3. Common Mobile Testing Scenarios:

Test API Error Handling:

  • Use Breakpoints to change response status to 500
  • Verify app shows appropriate error message
  • Check if retry mechanism works

Test Offline Mode:

  • Use Map Local to return cached responses
  • Block specific requests
  • Verify offline functionality

Test Different API Versions:

  • Use Map Remote to point to different API versions
  • Test backward compatibility
  • Test migration scenarios

Test Slow Networks:

  • Apply throttling (3G settings)
  • Verify loading states
  • Check timeout handling
  • Test progressive image loading

Capture for Bug Reports:

  • Record complete session
  • Export HAR file
  • Include in bug report with steps to reproduce

Choosing the Right Tools

IDE Selection Matrix

Use CaseVS CodeIntelliJ IDEA
JavaScript/TypeScript tests✓✓✓ Excellent✓✓ Good
Java test automation✓ Basic✓✓✓ Excellent
Python testing✓✓✓ Excellent (with extensions)✓✓ Good (PyCharm better)
Multi-language projects✓✓✓ Excellent✓✓ Good
Lightweight/Fast startup✓✓✓ Excellent✓ Slower
Built-in features✓ Needs extensions✓✓✓ Excellent
Free/Open source✓✓✓ Free✓ Community Edition
API testing✓✓ Good (extensions)✓✓✓ Built-in

Frontend Test Automation:

  • IDE: VS Code
  • Extensions: Playwright, Jest, ESLint
  • Browser: Chrome DevTools
  • Proxy: Charles

Backend API Testing:

  • IDE: IntelliJ IDEA / VS Code
  • Tools: REST Client, Postman
  • Proxy: Charles / Fiddler
  • Database: DBeaver / IntelliJ Database Tools

Mobile Testing:

  • IDE: VS Code / Android Studio
  • Proxy: Charles (best mobile support)
  • Device Mirroring: scrcpy
  • Performance: Chrome DevTools (remote debugging)

Full Stack Testing:

  • IDE: VS Code (multi-root workspace)
  • Browser: Chrome DevTools
  • API: IntelliJ HTTP Client / Thunder Client
  • Proxy: Charles

Learning Path

Week 1-2: IDE Basics

  • Set up VS Code or IntelliJ IDEA
  • Install essential extensions/plugins
  • Learn keyboard shortcuts
  • Configure debugging
  • Create custom snippets

Week 3-4: Browser DevTools

  • Master Elements and Console panels
  • Learn Network analysis
  • Practice JavaScript debugging
  • Create reusable snippets
  • Run Lighthouse audits

Week 5-6: Proxy Tools

  • Install and configure Charles/Fiddler
  • Set up SSL proxying
  • Practice request modification
  • Create mock responses with Map Local
  • Test mobile apps

Week 7-8: Advanced Techniques

  • Combine tools in testing workflow
  • Create automated test helpers
  • Build custom debugging scripts
  • Document team best practices
  • Train other team members

Productivity Tips

1. Keyboard Shortcuts Learn these first:

  • VS Code: Cmd/Ctrl + P (quick open), Cmd/Ctrl + Shift + P (command palette)
  • DevTools: Cmd/Ctrl + Shift + C (inspect element), Cmd + K (clear console)
  • Charles: Cmd/Ctrl + K (clear session), Cmd/Ctrl + R (start/stop recording)

2. Custom Snippets Create snippets for:

  • Common test patterns
  • API request templates
  • Console debugging scripts
  • Mock data generators

3. Workspace Organization

  • Use multi-root workspaces for complex projects
  • Create .vscode/tasks.json for common operations
  • Save debugging configurations
  • Organize proxy sessions by feature

4. Documentation Document in your team wiki:

  • IDE setup instructions
  • Required extensions/plugins
  • Debugging configurations
  • Proxy setup for projects
  • Common troubleshooting steps

5. Automation Automate repetitive tasks:

  • Test execution scripts
  • Coverage report generation
  • HAR file analysis scripts
  • Network performance monitoring

Conclusion

Mastering the right tools transforms testing efficiency. VS Code and IntelliJ IDEA provide powerful environments for test development with the right extensions and configurations. Browser DevTools offer unmatched insight into application behavior. Proxy tools like Charles and Fiddler enable deep API inspection and manipulation.

The key is not to learn every feature of every tool, but to:

  1. Choose tools that fit your tech stack
  2. Master the features you use daily (80/20 rule)
  3. Automate repetitive tasks with snippets and scripts
  4. Document your setup for team consistency
  5. Continuously learn as tools evolve

Start with one tool from each category (IDE, DevTools, Proxy), build proficiency, then expand your toolkit. Remember: tools are force multipliers, but testing expertise is what matters most.

Next Steps:

  1. Set up your primary IDE with essential extensions today
  2. Practice browser DevTools daily during testing
  3. Install and configure a proxy tool this week
  4. Create your first custom snippet or debugging configuration
  5. Share your learnings with your team

Happy testing!