# 测试文档 > **⚠ 结构时效警示(2026-08-31 全站一致性审计)**:本文档描述的 `e2e/src/` 分层结构(config/data/fixtures/pages/tests 子目录、Page Object 模式)与当前代码**不符**——现行 `e2e/` 为**扁平 spec 结构**(如 `cases-filter.spec.ts`、`user-journey.spec.ts` 等直接位于 `e2e/` 根,配合 `playwright.config.ts`)。Page Object 类、fixtures 等示例代码在代码库中不存在,npm scripts 以实际 `package.json` 为准。本文档保留作 Playwright 使用参考,具体结构以代码为准。 ## 测试概述 项目使用 Playwright 进行端到端(E2E)测试,测试框架位于 `e2e/` 目录(扁平 spec 结构)。 ## 测试框架结构 ``` e2e/ ├── src/ │ ├── config/ # 配置文件 │ │ ├── environments.ts # 环境配置 │ │ └── network-configs.ts # 网络配置 │ ├── data/ # 测试数据 │ │ └── test-data.ts │ ├── fixtures/ # 测试 Fixtures │ │ ├── base.fixture.ts # 基础 Fixture │ │ └── a11y.fixture.ts # 可访问性 Fixture │ ├── pages/ # Page Object Model │ │ ├── BasePage.ts # 基础页面 │ │ ├── HomePage.ts # 首页 │ │ ├── AboutPage.ts # 关于页 │ │ ├── CasesPage.ts # 案例页 │ │ ├── ContactPage.ts # 联系页 │ │ ├── NewsPage.ts # 新闻页 │ │ ├── ProductsPage.ts # 产品页 │ │ ├── ServicesPage.ts # 服务页 │ │ └── SolutionsPage.ts # 解决方案页 │ └── tests/ # 测试用例 │ ├── accessibility/ # 可访问性测试 │ ├── debug/ # 调试测试 │ ├── deployment/ # 部署就绪测试 │ ├── error-handling/ # 错误处理测试 │ ├── mobile/ # 移动端测试 │ ├── performance/ # 性能测试 │ ├── regression/ # 回归测试 │ ├── responsive/ # 响应式测试 │ ├── security/ # 安全测试 │ ├── smoke/ # 冒烟测试 │ ├── utils/ # 工具测试 │ └── visual/ # 视觉回归测试 ├── playwright.config.ts # Playwright 配置 ├── package.json └── .env.example ``` ## 测试类型 ### 1. 冒烟测试 (Smoke Tests) **目录**: `e2e/src/tests/smoke/` **目的**: 验证核心功能是否正常工作 **测试文件**: - `all-pages.spec.ts` - 所有页面加载测试 - `home-page.smoke.spec.ts` - 首页冒烟测试 - `contact-page.smoke.spec.ts` - 联系页冒烟测试 - `navigation.smoke.spec.ts` - 导航冒烟测试 **运行命令**: ```bash npm run test:smoke # 或 npx playwright test --grep @smoke ``` ### 2. 回归测试 (Regression Tests) **目录**: `e2e/src/tests/regression/` **目的**: 确保新代码没有破坏现有功能 **测试文件**: - `contact-form.regression.spec.ts` - 联系表单回归测试 - `home-page.regression.spec.ts` - 首页回归测试 - `navigation.spec.ts` - 导航回归测试 **运行命令**(`package.json` 无 `test:regression` 脚本,真实入口是 `test:e2e:standard`): ```bash npm run test:e2e:standard # = cd e2e && npx playwright test --grep @regression ``` ### 3. 性能测试 (Performance Tests) **目录**: `e2e/src/tests/performance/` **目的**: 验证页面性能指标 **测试文件**: - `core-web-vitals.spec.ts` - Core Web Vitals 测试 - `performance.spec.ts` - 通用性能测试 - `image-loading.spec.ts` - 图片加载性能 - `interaction-performance.spec.ts` - 交互性能测试 **监控指标**: - LCP (Largest Contentful Paint) < 2.5s - FID (First Input Delay) < 100ms - CLS (Cumulative Layout Shift) < 0.1 - TTFB (Time to First Byte) < 600ms **运行命令**(两条入口不是一回事,勿混用): ```bash npm run test:performance # = k6 run tests/performance/load-test.js(压测脚本,不是 Playwright 用例;文件确在磁盘) npx playwright test --grep @performance # 浏览器内性能用例(e2e/mobile-performance.spec.ts) ``` `test:performance` / `test:stress` / `test:performance:api` / `test:performance:soak` 四条都依赖**本机 `k6` CLI**——`package.json` 里的 `k6@0.0.0` 只是 Grafana/LoadImpact 官方的「Dummy package for autocompleting k6 scripts」编辑器类型包,不含可执行文件(验收 N-10)。 ### 4. 响应式测试 (Responsive Tests) **目录**: `e2e/src/tests/responsive/` **目的**: 验证多设备适配 **测试文件**: - `responsive.spec.ts` - 响应式布局测试 - `mobile-interaction.spec.ts` - 移动端交互测试 **测试设备**: - Desktop: 1920x1080, 1366x768 - Tablet: iPad Pro (1024x1366), iPad Air (820x1180) - Mobile: iPhone 12 (390x844), iPhone SE (375x667), Pixel 5 (393x851) **运行命令**(⚠ `@responsive` 这个标签在当前 `e2e/*.spec.ts` 里**零命中**,`--grep @responsive` 会跑到 0 个用例;响应式覆盖由 project 维度承担,真实存在的入口只有这两条): ```bash npm run test:visual:tablet # visual-chromium-tablet(平板断点全页) npm run test:visual:mobile # visual-chromium-mobile(窄视口全页) # 功能侧的窄视口执行量在 chromium-mobile project(iPhone 14, 390×844): cd e2e && npx playwright test --project=chromium-mobile ``` ### 5. 可访问性测试 (Accessibility Tests) **目录**: `e2e/src/tests/accessibility/` **目的**: 验证 WCAG 合规性 **测试文件**: - `accessibility.spec.ts` - 可访问性测试 - `wcag-compliance.spec.ts` - WCAG 合规测试 **检查项**: - 颜色对比度 ≥ 4.5:1 (AA 级别);≥24px 大字档(含 `aria-hidden` 的装饰序号)按 1.4.3 的 3:1 判定——axe-core 的 `color-contrast` 不因 `aria-hidden` / `role="none"` / CSS `opacity` 豁免,装饰文字须自带合规对比度(用 `text-text-hint` 令牌) - 键盘导航支持 - 屏幕阅读器兼容 - ARIA 属性正确性 - 焦点顺序合理 - 触摸目标:硬门禁为 WCAG 2.2 AA SC 2.5.8 ≥ 24×24px(`e2e/touch-targets.ts` 的 `aaViolations`,须为 0);SC 2.5.5 ≥ 44×44px 属 AAA,仅作为建议清单打印不失败。历史上曾把 44px 误标为 AA,导致门禁长期红色。 **运行命令**(`package.json` 中真实存在的脚本;本节其余示例里的 `test:accessibility` / `test:responsive` 并不存在,勿照抄): ```bash npm run check:a11y # 静态令牌门禁伞:check:contrast + check:headings + check:brand-token(已并入 test:all) npm run check:contrast # 只读 globals.css 令牌表做配对计算(不启服务) npm run check:headings # 自起服务扫描渲染后的标题层级:存在 dist/standalone/server.js 时**直起 standalone**, # 产物缺失才回退 `npm run preview` 并打印告警(验收 N-24③,见 CLAUDE.md「Build & Preview」) npm run check:brand-token # 品牌红文字通道令牌化检查(静态扫描源码) npx playwright test --grep @accessibility # 浏览器内 axe / 触摸目标用例 ``` ### 6. 安全测试 (Security Tests) **目录**: `e2e/src/tests/security/` **目的**: 验证安全防护措施 **测试文件**: - `security.spec.ts` - 通用安全测试 - `xss-protection.spec.ts` - XSS 防护测试 - `csrf-protection.spec.ts` - CSRF 防护测试 **检查项**: - XSS 攻击防护 - CSRF Token 验证 - 安全头部配置 - 表单验证 **运行命令**(两条入口不是一回事,勿混用): ```bash npm run test:security # = npm audit --audit-level=high && npm run test:security:headers(依赖审计 + 线上响应头脚本,不跑 Playwright 用例) npx playwright test --grep @security # 浏览器侧的安全头用例(e2e/security-headers.spec.ts) ``` ### 7. 视觉回归测试 (Visual Tests) **测试文件**: `e2e/visual-regression.spec.ts`(L1 全页 15 页 × 5 project + L2 组件状态 + L3 主题 = `--list` 实测 **25 例/project × 5 project = 125 例**) > ⚠ 三个口径别混:`VISUAL_TEST_PAGES` 的**页面数** 15、每 project 的**用例数** 25、磁盘上的**参照 PNG 数** 107(5 个 project 目录各 21 张 + 目录外 `manual-acceptance/` 2 张)。用例数 − 参照数 ≠ 0 的那部分是**覆盖空洞**而非「多余用例」——`/products/erp-upgrade` 与 `/about/brand` 在两页于 5 个 project 下均无参照,另有卡片/输入框两例死在选择器上(`[class*="card"]` 零匹配、`input[type="text"]` 的 `.first()` 命中按设计隐藏的反垃圾蜜罐)。定性见 [docs/acceptance/2026-09-23-gates/final-verdict.md](acceptance/2026-09-23-gates/final-verdict.md) N-15 与 A-9。**`@visual` 标签不存在**(`e2e/*.spec.ts` 内零命中),视觉层只按 project / spec 文件选取。 **Project**: `visual-chromium-desktop` / `-tablet` / `-mobile` / `visual-firefox-desktop` / `visual-webkit-desktop`,全部 `reducedMotion: 'reduce'` **快照目录**: `e2e/visual-snapshots/{projectName}/{testFilePath}/{arg}-{projectName}{ext}`(模板见 `e2e/playwright.config.ts`) **运行命令**: ```bash npm run test:visual # 仅 chromium 桌面 npm run test:visual:all # 5 个 project 全量 npm run test:visual:browsers # 三引擎桌面 ``` **更新快照**: ```bash npm run test:visual:all -- --update-snapshots ``` **确定性约束**(2026-09-21 验收 83 例失败的根因,详见 [docs/lessons-learned.md](lessons-learned.md) §5.14 / §5.15): 1. 快照与 `E2E_TARGET` 无关——`e2e/fixtures.ts` 移除 `next dev` 注入的 ``(左下角 devtools 指示器),否则 dev 采集的基线在 production 复核时每个全页都多出同一簇。 2. 视觉阶段不得与写库用例并发——`npm run test` 已拆为 `test:functional` → `test:visual:all` 两阶段串行。CMS 用例「建条目 → revalidate → 删条目」若与截图并发,生产 server 的预渲染缓存会保留含测试条目的那一版(`x-nextjs-cache: HIT`),数据行删干净了页面仍是脏的。 3. dev 指示器由**测试夹具自己剥掉**,不是靠配置关掉——`e2e/fixtures.ts` 的 `context` 夹具注入 init script,用 `document.querySelectorAll('nextjs-portal').forEach(n => n.remove())` 移除 `next dev` 注入的 ``(挂 MutationObserver 于 `document`,因为 document start 时 `documentElement` 还是 null)。它内部 shadow DOM 的 `