Skip to content

E2E Testing Overview

20.5.1. Framework Selection

Playwright is the recommended E2E testing framework.

ItemPlaywrightCypress
Browser SupportChromium, Firefox, WebKitChromium, Firefox, WebKit (experimental)
Execution SpeedFast (parallel execution supported by default)Moderate (paid plan required for parallel execution)
Multiple Tabs/WindowsSupportedNot supported
iframe SupportNative supportLimited
API TestingBuilt-in supportPlugin required
Debugging ToolsTrace Viewer, CodegenCypress Runner
Language SupportTypeScript, JavaScript, Python, Java, .NETTypeScript, JavaScript
  • Playwright natively supports multi-browser testing, parallel execution, and API testing, making it the TQS recommended framework.
  • Projects already using Cypress are not required to migrate; however, new projects must adopt Playwright.

20.5.2. Core Scenarios

E2E tests verify the user's critical business workflows. The following scenarios are mandatory test targets.

ScenarioVerification Items
Login/LogoutSuccessful login, invalid credentials handling, redirect after logout
CRUD FlowItem creation, list retrieval, detail view, update, deletion
Error Handling404 page, user feedback on server errors, network error recovery
Access ControlBlocking unauthenticated user access, menu/feature visibility by permission
Form SubmissionValidation, duplicate submission prevention, success/failure feedback
typescript
// e2e/auth.spec.ts
import { test, expect } from '@playwright/test'

test.describe('Authentication Flow', () => {
  test('should navigate to dashboard after successful login', async ({ page }) => {
    await page.goto('/login')
    await page.fill('[data-testid="input-email"]', 'user@example.com')
    await page.fill('[data-testid="input-password"]', 'password123')
    await page.click('[data-testid="btn-login"]')

    await expect(page).toHaveURL('/dashboard')
    await expect(page.locator('[data-testid="user-greeting"]')).toBeVisible()
  })

  test('should display an error message for incorrect password', async ({ page }) => {
    await page.goto('/login')
    await page.fill('[data-testid="input-email"]', 'user@example.com')
    await page.fill('[data-testid="input-password"]', 'wrong')
    await page.click('[data-testid="btn-login"]')

    await expect(page.locator('[data-testid="error-message"]')).toBeVisible()
  })
})
  • All core scenarios must be tested for both happy paths and error paths.
  • Test scenarios must be mapped to user stories or requirements documents for management.

20.5.3. Test Writing Principles

User-Perspective Testing

E2E tests must be written based on elements the user sees and interacts with, not internal implementation details.

  • Tests must not depend on CSS class names or internal component state.
  • Use data-testid attributes to select test target elements.
  • data-testid naming convention: {elementType}-{description} (e.g., btn-submit, input-email, list-users)

Preventing Flaky Tests

Flaky tests undermine reliability; therefore, the following principles must be observed.

  • Use condition-based waiting (waitForSelector, expect().toBeVisible()) instead of fixed wait times (waitForTimeout).
  • Test data must be independently created and cleaned up within each test.
  • External API dependencies should be replaced with mock servers whenever possible.
  • Use waitForResponse() to explicitly wait for network request completion.

20.5.4. CI Integration

The following configuration is required for automated E2E test execution in CI environments.

typescript
// playwright.config.ts
import { defineConfig } from '@playwright/test'

export default defineConfig({
  testDir: './e2e',
  fullyParallel: true,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    video: 'on-first-retry',
  },
  webServer: {
    command: 'yarn dev',
    port: 3000,
    reuseExistingServer: !process.env.CI,
  },
})
ConfigurationCI ValueDescription
retries2Maximum 2 retries on failure
workers1Serial execution for stability
screenshotonly-on-failureAutomatic screenshot capture on failure
videoon-first-retryVideo recording on first retry
traceon-first-retryTrace file saved on first retry
  • Tests must run in headless mode in CI environments (Playwright default).
  • Screenshots, videos, and Trace files generated on failure must be retained as CI artifacts.
  • The webServer configuration automatically starts the development server before testing.
  • Retries are enabled only in CI so that failures are immediately visible during local development.

TIENIPIA QUALIFIED STANDARD