news 2026/9/9 12:59:10

Pruebas en TypeScript/JavaScript

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Pruebas en TypeScript/JavaScript

Pruebas en TypeScript/JavaScript

【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC

Este archivo extiende common/testing.md con contenido específico de TypeScript/JavaScript.

Testing E2E

UsarPlaywrightcomo framework de testing E2E para flujos de usuario críticos.

Soporte de Agentes

  • e2e-runner- Especialista en testing E2E con Playwright
其 YAML frontmatter 的 `paths` 决定了规则的自动触发范围(所有 TS/TSX/JS/JSX 文件): ```yaml paths: - "**/*.ts" - "**/*.tsx" - "**/*.js" - "**/*.jsx"

按 rules/README.md 中「语言特定规则优先于通用规则」的约定(类似 CSS 特异性),本文件是对通用测试要求的唯一 TypeScript 覆盖点;它本身没有对通用层的覆盖率门槛或 TDD 做任何放宽,因此必须与 rules/common/testing.md 一起阅读生效。安装时应整目录复制(避免/*展开破坏../common/相对引用),参见 rules/README.md。

二、底层红线:80% 覆盖率与三类测试全量必选

该语言规则没有降低通用层的强制要求。rules/common/testing.md 明确规定了每个 TypeScript/JavaScript 项目都必须同时具备:

测试类型对象典型落点
Unit Tests(单元测试)单个函数、工具、组件*.test.ts与源码同目录
Integration Tests(集成测试)API 端点、数据库操作tests/integration/
E2E Tests(端到端测试)关键用户流程tests/e2e/*.spec.ts

其中 E2E 层的框架选择,正是本语言规则唯一明确指定的事项:Playwright。这条规则同时出现在 rules/typescript/testing.md 及其西班牙语镜像 docs/es/rules/typescript/testing.md 中,说明它是跨翻译版本被一致执行的语言级决策。

三、强制 TDD:先写测试(RED → GREEN → IMPROVE)

通用规则要求所有 TypeScript 功能开发遵循 TDD 强制流程(rules/common/testing.md):

  1. 先写测试(RED)——测试应先失败;
  2. 运行测试,确认失败;
  3. 编写最小实现(GREEN)——让测试通过;
  4. 重构(IMPROVE);
  5. 校验覆盖率 ≥ 80%。

配套的 agent 是tdd-guide(见 agents/tdd-guide.md),其职责是在新功能开发时主动(PROACTIVELY)强制执行「先写测试」。规则还特别强调排障纪律:优先调用 tdd-guide、检查测试隔离性、核对 mock 是否正确,并且在测试本身无误时修改实现而非修改测试

四、测试结构规范:AAA 模式与行为化命名

4.1 AAA(Arrange-Act-Assert)三段式

通用规则以 TypeScript 示例约定了测试的标准结构(rules/common/testing.md):

test('calculates similarity correctly', () => { // Arrange const vector1 = [1, 0, 0] const vector2 = [0, 1, 0] // Act const similarity = calculateCosineSimilarity(vector1, vector2) // Assert expect(similarity).toBe(0) })

4.2 行为化命名

测试名必须描述被测行为而非实现细节:

test('returns empty array when no markets match query', () => {}) test('throws error when API key is missing', () => {}) test('falls back to substring search when Redis is unavailable', () => {})

这种命名的价值在 E2E 场景被进一步放大:行为化描述天然映射到用户旅程(user journey),便于 e2e-runner 在生成用例时直接翻译为「用户动作 + 断言」。

五、E2E 层深挖:Playwright 与专职 agent e2e-runner

语言规则在 E2E 上的落地不止是选型,还绑定了执行主体e2e-runner(完整定义见 agents/e2e-runner.md),其核心职责包括:

  1. Test Journey Creation——为关键用户流程编写测试(优先 Agent Browser,回退 Playwright);
  2. Test Maintenance——随 UI 变更维护用例;
  3. Flaky Test Management——识别并隔离不稳定测试;
  4. Artifact Management——采集截图、视频、trace;
  5. CI/CD Integration——保证流水线内稳定运行;
  6. Test Reporting——产出 HTML 报告与 JUnit XML。

在 ECC 的命令体系中,这一能力通过/e2e命令暴露给用户(见 docs/es/commands/e2e.md),典型触发场景包括登录、交易、支付等高风险关键流程,以及在发布前验证前后端集成。

5.1 工具优先级:Agent Browser 优先,Playwright 兜底

e2e-runner 的默认偏好是Agent Browser(语义化选择器、AI 优化、内置自动等待,底层构建于 Playwright):

npm install -g agent-browser && agent-browser install agent-browser open https://example.com agent-browser snapshot -i # 获取带 [ref=e1] 引用的元素 agent-browser click @e1 # 按引用点击 agent-browser fill @e2 "text" # 填充输入框 agent-browser wait visible @e5 # 等待元素可见 agent-browser screenshot result.png

当 Agent Browser 不可用时,回退到原生 Playwright:

npx playwright test # 运行全部 E2E 用例 npx playwright test tests/auth.spec.ts # 只跑指定文件 npx playwright test --headed # 有头模式查看浏览器 npx playwright test --debug # 调试器逐行运行 npx playwright test --trace on # 带 trace 运行 npx playwright show-report # 打开 HTML 报告

5.2 Playwright 配置基线

sdks 中提供了可直接落地的playwright.config.ts,覆盖多浏览器项目、CI 差异化重试与多种报告器:

import { defineConfig, devices } from '@playwright/test' export default defineConfig({ testDir: './tests/e2e', fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: [ ['html', { outputFolder: 'playwright-report' }], ['junit', { outputFile: 'playwright-results.xml' }], ['json', { outputFile: 'playwright-results.json' }] ], use: { baseURL: process.env.BASE_URL || 'http://localhost:3000', trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure', actionTimeout: 10000, navigationTimeout: 30000, }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, { name: 'webkit', use: { ...devices['Desktop Safari'] } }, { name: 'mobile-chrome', use: { ...devices['Pixel 5'] } }, ], webServer: { command: 'npm run dev', url: 'http://localhost:3000', reuseExistingServer: !process.env.CI, timeout: 120000, }, })

关键参数解读:

  • trace: 'on-first-retry':首次失败自动重试并捕获 trace,是最省存储的失败调试策略;
  • screenshot: 'only-on-failure'+video: 'retain-on-failure':只在失败时保留证据,对应 e2e-runner 的制品管理职责;
  • retries/workers在 CI 与本地差异化:CI 上收紧并发(workers: 1)换取稳定性;
  • 三个reporter并行输出:HTML 给人看,JUnit/JSON 喂给 CI 与脚本。

5.3 Page Object Model(POM)范式

e2e-runner 的用例生成与 skill 均强调 POM,将页面选择器与交互封装为类:

import { Page, Locator } from '@playwright/test' export class ItemsPage { readonly page: Page readonly searchInput: Locator readonly itemCards: Locator readonly createButton: Locator constructor(page: Page) { this.page = page this.searchInput = page.locator('[data-testid="search-input"]') this.itemCards = page.locator('[data-testid="item-card"]') this.createButton = page.locator('[data-testid="create-btn"]') } async goto() { await this.page.goto('/items') await this.page.waitForLoadState('networkidle') } async search(query: string) { await this.searchInput.fill(query) await this.page.waitForResponse(resp => resp.url().includes('/api/search')) await this.page.waitForLoadState('networkidle') } async getItemCount() { return await this.itemCards.count() } }

配套的测试骨架遵循test.describe+beforeEach组织用例,并在关键步骤放置expect断言(skills/e2e-testing/SKILL.md):

import { test, expect } from '@playwright/test' import { ItemsPage } from '../../pages/ItemsPage' test.describe('Item Search', () => { let itemsPage: ItemsPage test.beforeEach(async ({ page }) => { itemsPage = new ItemsPage(page) await itemsPage.goto() }) test('should search by keyword', async ({ page }) => { await itemsPage.search('test') const count = await itemsPage.getItemCount() expect(count).toBeGreaterThan(0) await expect(itemsPage.itemCards.first()).toContainText(/test/i) await page.screenshot({ path: 'artifacts/search-results.png' }) }) test('should handle no results', async ({ page }) => { await itemsPage.search('xyznonexistent123') await expect(page.locator('[data-testid="no-results"]')).toBeVisible() expect(await itemsPage.getItemCount()).toBe(0) }) })

六、关键用户流程的端到端验证实战

docs/es/commands/e2e.md 给出了 e2e-runner 的完整工作样例:将「搜索市场 → 查看结果 → 点击进入 → 查看详情」的用户旅程翻译为多场景用例,并在每个关键步骤验证 API 响应、页面状态与截图取证。

6.1 场景设计三要素

场景类型示例断言重点
Happy path(主路径)搜索关键词并进入详情页标题匹配、URL 形态/markets/[id]、图表渲染
边界情形(empty state)搜索不存在的市场no-results可见、卡片数为 0
反向操作清空搜索恢复全部计数回到初始值

E2E 中等待的真实形态是等待条件而非固定时长,这正是 unstable 测试的主要来源之一:

// 错误:任意超时 await page.waitForTimeout(5000) // 正确:等待具体网络条件 await page.waitForResponse(resp => resp.url().includes('/api/data')) // 正确:使用自动等待的 locator await page.locator('[data-testid="button"]').click()

6.2 高风险流程:金融/交易与 Web3

对于金融与支付类关键流程,skill 强调三个原则:绝不针对生产环境执行真实资金操作、通过 mock 注入链上/provider 行为、对交易确认使用带{ timeout }的响应等待:

test('trade execution', async ({ page }) => { // Skip on production — real money test.skip(process.env.NODE_ENV === 'production', 'Skip on production') await page.goto('/markets/test-market') await page.locator('[data-testid="position-yes"]').click() await page.locator('[data-testid="trade-amount"]').fill('1.0') const preview = page.locator('[data-testid="trade-preview"]') await expect(preview).toContainText('1.0') await page.locator('[data-testid="confirm-trade"]').click() await page.waitForResponse( resp => resp.url().includes('/api/trade') && resp.status() === 200, { timeout: 30000 } ) await expect(page.locator('[data-testid="trade-success"]')).toBeVisible() })

七、不稳定测试(Flaky)治理:隔离、重跑与指标

e2e-runner 与 skill 共同定义了 flaky 治理闭环:

定位问题(本地重跑放大):

npx playwright test tests/search.spec.ts --repeat-each=10 npx playwright test tests/search.spec.ts --retries=3

隔离问题用例(quarantine):

test('flaky: complex search', async ({ page }) => { test.fixme(true, 'Flaky - Issue #123') }) test('conditional skip', async ({ page }) => { test.skip(process.env.CI, 'Flaky in CI - Issue #123') })

三类高频成因与修法(来自 skills/e2e-testing/SKILL.md):

成因反模式修法
竞态条件假设元素就绪后裸page.click()用自动等待 locatorpage.locator(...).click()
网络时序waitForTimeout(5000)waitForResponse(url 匹配)
动画时序动画播放期间点击waitFor({ state: 'visible' })+networkidle

成功指标(agents/e2e-runner.md):关键流程通过率 100%、整体通过率 > 95%、flaky 率 < 5%、单次测试时长 < 10 分钟、制品可访问。

八、CI/CD 集成与报告产物

规则要求 E2E 在合入主干(merge to main)前执行。Playwright 官方 GitHub Actions 流程可直接对接:

name: E2E Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: npm ci - run: npx playwright install --with-deps - run: npx playwright test env: BASE_URL: ${{ vars.STAGING_URL }} - uses: actions/upload-artifact@v4 if: always() with: name: playwright-report path: playwright-report/ retention-days: 30

产物规范:每次运行生成 HTML 报告与 JUnit XML(供 CI 消费);仅失败时保留截图、视频、trace 压缩包、网络与控制台日志。本地排查命令:

npx playwright show-report # HTML 报告 npx playwright show-trace artifacts/trace.zip # 单步回放 trace

【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 12:56:28

AI Agent本地开发中的代理陷阱与协议适配实践

1. “ruflo”不是工具名&#xff0c;而是当前AI开发圈里一个被误传的“幽灵关键词” 最近两周&#xff0c;我在几个技术群和开发者论坛里反复看到“ruflo”这个词——它总和 claude code 、 codex 、 npx 、 agent 这些词捆在一起出现&#xff0c;比如“ruflo安装失败”…

作者头像 李华
网站建设 2026/9/9 12:55:53

ModuleNotFoundError 别慌:Python 环境与 pip 安装错位排查实战指南

你很可能也遇到过这种情况&#xff1a;在终端里明明敲了pip install jupyterlab&#xff0c;提示安装成功&#xff0c;结果一运行jupyter lab或者启动某个 Python 脚本&#xff0c;迎面就是一行红字ModuleNotFoundError: No module named jupyterlab。这类报错算得上 Python 生…

作者头像 李华
网站建设 2026/9/9 12:55:22

风力发电与压缩空气储能联合运行建模及Matlab仿真实现

风电这块儿&#xff0c;大家做功率预测、做并网控制&#xff0c;核心痛点一直很稳定&#xff1a;风是间歇的&#xff0c;风电出力也跟着犯神经&#xff0c;今天风大明天没风&#xff0c;上午十分钟内风速能跳好几米每秒&#xff0c;电网那边调度看着功率曲线直摇头。要让风电从…

作者头像 李华