Skip to main content

Testing Methodologies

Comprehensive testing approaches and methodologies for FLYPILOT projects.

Testing Pyramid

         /\
/ \
/ E2E\
/------\
/ Integ \
/----------\
/ Unit \
/--------------\
LevelCoverageSpeedCost
UnitComponents, functionsFastLow
IntegrationAPI, servicesMediumMedium
E2EUser journeysSlowHigh

Unit Testing

What to Test

  • Individual functions and utilities
  • React components in isolation
  • State management logic
  • Data transformations

Tools

StackFrameworkRunner
React/Next.jsJest + React Testing LibraryJest
WordPressPHPUnitWP CLI
Node.jsJest or VitestNative

Example: React Component

// Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
it('renders with text', () => {
render(<Button>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});

it('calls onClick when clicked', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);
fireEvent.click(screen.getByText('Click me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});

it('is disabled when disabled prop is true', () => {
render(<Button disabled>Click me</Button>);
expect(screen.getByText('Click me')).toBeDisabled();
});
});

Example: Utility Function

// utils/formatPrice.test.ts
import { formatPrice } from './formatPrice';

describe('formatPrice', () => {
it('formats whole numbers', () => {
expect(formatPrice(100)).toBe('$100.00');
});

it('formats decimals', () => {
expect(formatPrice(99.99)).toBe('$99.99');
});

it('handles zero', () => {
expect(formatPrice(0)).toBe('$0.00');
});

it('handles negative numbers', () => {
expect(formatPrice(-50)).toBe('-$50.00');
});
});

Integration Testing

What to Test

  • API endpoint responses
  • Database operations
  • Third-party service integrations
  • Authentication flows

Example: API Endpoint

// api/users.test.ts
import { createMocks } from 'node-mocks-http';
import handler from '@/app/api/users/route';

describe('/api/users', () => {
it('returns users list', async () => {
const { req, res } = createMocks({
method: 'GET',
});

await handler(req, res);

expect(res._getStatusCode()).toBe(200);
expect(JSON.parse(res._getData())).toHaveProperty('users');
});

it('creates a new user', async () => {
const { req, res } = createMocks({
method: 'POST',
body: {
name: 'Test User',
email: 'test@example.com',
},
});

await handler(req, res);

expect(res._getStatusCode()).toBe(201);
expect(JSON.parse(res._getData())).toHaveProperty('id');
});

it('returns 400 for invalid data', async () => {
const { req, res } = createMocks({
method: 'POST',
body: {
name: '', // Invalid: empty name
},
});

await handler(req, res);

expect(res._getStatusCode()).toBe(400);
});
});

End-to-End Testing

What to Test

  • Critical user journeys
  • Checkout flows
  • Authentication flows
  • Form submissions

Tools

ToolBest For
PlaywrightCross-browser, modern
CypressDeveloper experience
PuppeteerChrome-specific

Example: Playwright

// tests/checkout.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Checkout Flow', () => {
test('completes purchase successfully', async ({ page }) => {
// Navigate to product
await page.goto('/products/test-product');

// Add to cart
await page.click('[data-testid="add-to-cart"]');
await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1');

// Go to checkout
await page.click('[data-testid="checkout-button"]');
await expect(page).toHaveURL('/checkout');

// Fill shipping info
await page.fill('[name="email"]', 'test@example.com');
await page.fill('[name="name"]', 'Test User');
await page.fill('[name="address"]', '123 Test St');
await page.fill('[name="city"]', 'Test City');
await page.fill('[name="zip"]', '12345');

// Fill payment info (test mode)
await page.fill('[name="cardNumber"]', '4242424242424242');
await page.fill('[name="expiry"]', '12/25');
await page.fill('[name="cvc"]', '123');

// Complete purchase
await page.click('[data-testid="place-order"]');

// Verify success
await expect(page).toHaveURL(/\/order-confirmation/);
await expect(page.locator('h1')).toContainText('Thank you');
});
});

Visual Regression Testing

Tools

  • Percy - CI integration, snapshot comparison
  • Chromatic - Storybook integration
  • BackstopJS - Open source

When to Use

  • Design system components
  • Marketing pages with precise designs
  • After major refactors

Accessibility Testing

Automated Tools

  • axe DevTools - Browser extension
  • jest-axe - Jest integration
  • Lighthouse - Built into Chrome

Manual Testing Checklist

  • Navigate entire site with keyboard only
  • Test with screen reader (VoiceOver/NVDA)
  • Check color contrast ratios
  • Verify focus indicators are visible
  • Test with zoom at 200%

Example: Jest Accessibility Test

import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
import { LoginForm } from './LoginForm';

expect.extend(toHaveNoViolations);

describe('LoginForm Accessibility', () => {
it('has no accessibility violations', async () => {
const { container } = render(<LoginForm />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
});

Performance Testing

Metrics to Monitor

  • Time to First Byte (TTFB)
  • First Contentful Paint (FCP)
  • Largest Contentful Paint (LCP)
  • Time to Interactive (TTI)
  • Total Blocking Time (TBT)

Tools

  • Lighthouse CI - Automated in CI/CD
  • WebPageTest - Detailed analysis
  • Chrome DevTools - Performance panel

Performance Budget

{
"performance": [
{
"metric": "first-contentful-paint",
"budget": 1800
},
{
"metric": "largest-contentful-paint",
"budget": 2500
},
{
"metric": "total-blocking-time",
"budget": 300
},
{
"metric": "cumulative-layout-shift",
"budget": 0.1
}
]
}

Testing Workflow

Pre-Commit

  1. Run linting
  2. Run unit tests
  3. Run type checking

Pull Request

  1. All pre-commit checks
  2. Integration tests
  3. Visual regression (if configured)
  4. Accessibility checks

Pre-Deploy

  1. Full test suite
  2. E2E tests
  3. Performance audit
  4. Security scan

Post-Deploy

  1. Smoke tests on production
  2. Monitor error rates
  3. Check Core Web Vitals

Test Coverage

Aim for 80%+ unit test coverage on critical paths. Don't test everything - focus on business logic and complex interactions.