From 31e86820070c71e21b0d7a2a8c94948c4e4a90a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Fri, 13 Mar 2026 11:24:40 +0800 Subject: [PATCH] feat: add test tier configuration and tiered playwright config --- e2e/playwright.config.tiered.ts | 116 ++++++++++++++++++++++++++++++++ e2e/src/config/test-tiers.ts | 47 +++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 e2e/playwright.config.tiered.ts create mode 100644 e2e/src/config/test-tiers.ts diff --git a/e2e/playwright.config.tiered.ts b/e2e/playwright.config.tiered.ts new file mode 100644 index 0000000..82c452d --- /dev/null +++ b/e2e/playwright.config.tiered.ts @@ -0,0 +1,116 @@ +import { defineConfig, devices } from '@playwright/test'; +import { getEnvironment } from './src/config/environments'; +import { getMobileDevices } from './src/utils/devices'; +import { getTestTier, TEST_TIERS } from './src/config/test-tiers'; + +const env = getEnvironment(); + +function createTieredConfig(tierName: string) { + const tier = getTestTier(tierName); + + return defineConfig({ + testDir: './src/tests', + fullyParallel: tier.fullyParallel, + forbidOnly: !!process.env.CI, + retries: tier.retries, + workers: tier.workers, + globalSetup: require.resolve('./global-setup'), + reporter: [ + ['html', { open: 'never' }], + ['json', { outputFile: `test-results/${tierName}-results.json` }], + ['junit', { outputFile: `test-results/${tierName}-junit.xml` }], + ['line'], + ['list'], + ['allure-playwright', { + outputFolder: 'allure-results', + detail: true, + suiteTitle: false, + }], + ], + timeout: tier.timeout, + expect: { + timeout: tier.timeout / 2, + }, + use: { + baseURL: env.baseURL, + trace: env.trace, + screenshot: env.screenshot, + video: env.video, + headless: true, + viewport: { width: 1280, height: 720 }, + actionTimeout: tier.timeout / 2, + navigationTimeout: tier.timeout, + launchOptions: { + slowMo: env.slowMo, + }, + storageState: '.auth/admin.json', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'chromium-coverage', + use: { + ...devices['Desktop Chrome'], + browserName: 'chromium', + }, + testMatch: tier.testMatch, + }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + { + name: 'Mobile Chrome', + use: { ...devices['Pixel 5'] }, + }, + { + name: 'Mobile Safari', + use: { ...devices['iPhone 12'] }, + }, + ...getMobileDevices().map(device => ({ + name: `mobile-${device.name.replace(/\s+/g, '-').toLowerCase()}`, + use: { + ...devices['Mobile Chrome'], + viewport: device.viewport, + userAgent: device.userAgent, + deviceScaleFactor: device.deviceScaleFactor, + isMobile: true, + }, + })), + { + name: 'performance-mobile', + use: { + ...devices['Mobile Chrome'], + viewport: { width: 375, height: 667 }, + isMobile: true, + }, + testMatch: /.*\.perf\.spec\.ts/, + }, + { + name: 'pwa-mobile', + use: { + ...devices['Mobile Chrome'], + viewport: { width: 375, height: 667 }, + isMobile: true, + serviceWorkers: 'allow', + }, + testMatch: /.*\.pwa\.spec\.ts/, + }, + ], + webServer: env.name === 'development' && !process.env.DISABLE_WEB_SERVER ? { + command: 'cd .. && npm run dev', + url: 'http://localhost:3000', + timeout: 120000, + reuseExistingServer: !process.env.CI, + } : undefined, + }); +} + +export default createTieredConfig(process.env.TEST_TIER || 'standard'); \ No newline at end of file diff --git a/e2e/src/config/test-tiers.ts b/e2e/src/config/test-tiers.ts new file mode 100644 index 0000000..8993fdd --- /dev/null +++ b/e2e/src/config/test-tiers.ts @@ -0,0 +1,47 @@ +export interface TestTierConfig { + name: string; + description: string; + testMatch: string | RegExp; + timeout: number; + retries: number; + workers: number | string; + fullyParallel: boolean; + failFast: boolean; +} + +export const TEST_TIERS: Record = { + fast: { + name: '快速层', + description: '冒烟测试、API测试、基础功能验证', + testMatch: /.*\.smoke\.spec\.ts$|.*\.api\.spec\.ts$/, + timeout: 30000, + retries: 1, + workers: process.env.CI ? 6 : '75%', + fullyParallel: true, + failFast: true, + }, + standard: { + name: '标准层', + description: '功能测试、响应式测试、移动端核心功能', + testMatch: /.*(admin|navigation|responsive|mobile).*\.spec\.ts$/, + timeout: 60000, + retries: 2, + workers: process.env.CI ? 4 : '50%', + fullyParallel: true, + failFast: false, + }, + deep: { + name: '深度层', + description: '视觉回归、性能测试、完整回归测试', + testMatch: /.*(visual|performance|regression).*\.spec\.ts$/, + timeout: 120000, + retries: 3, + workers: process.env.CI ? 2 : '25%', + fullyParallel: false, + failFast: false, + }, +}; + +export function getTestTier(tierName: string): TestTierConfig { + return TEST_TIERS[tierName] || TEST_TIERS.standard; +} \ No newline at end of file