Cypress

npm install @tracera/cypress

已在 Node.js 22.19–26.12 和 Cypress 14–16.2 上测试(见 自动化测试适配器)。@tracera/cypress。

在 cypress.config.ts 中:

import { defineConfig } from 'cypress';
import { registerTraceraPlugin } from '@tracera/cypress';

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      return registerTraceraPlugin(on, config);
    },
    supportFile: 'cypress/support/e2e.ts',
  },
});

在 support 文件中:

import '@tracera/cypress/support';

对于组件测试(Component Testing),从 component.setupNodeEvents 调用 registerTraceraPlugin,并在组件测试的 support 文件中导入相同的 support 入口。

环境变量、运行模式与重试见 自动化测试适配器。

重试时 Env 键:CYPRESS_RETRY。

绑定 testCaseId 与 autotestName

从 @tracera/cypress/runtime 导入 tracera 和 annotations,或在测试中使用 cy.traceraTestCase(需在 support 文件中有 import '@tracera/cypress/support')。annotations 名称为字面量(无 {param})。

在声明时(推荐 — 即使提前 this.skip() 也会绑定):

import { annotations } from '@tracera/cypress/runtime';

it('login', annotations(42, 'e2e/login'), () => {
  cy.visit('/login');
  cy.get('[data-testid=sign-in]').should('be.visible');
});

在测试中(若 annotations 已绑定用例则可省略):

import { tracera } from '@tracera/cypress/runtime';

it('login', () => {
  tracera.testCase(42, 'e2e/login');
  cy.visit('/login');
  cy.get('[data-testid=sign-in]').should('be.visible');
});

或者:cy.traceraTestCase(42, "e2e/login")。

Skip

使用 Cypress 标准 skip(this.skip())可选:在调用 skip 前用 tracera.comment 写入结果 comment

import { tracera, annotations } from '@tracera/cypress/runtime';

it('login', annotations(42, 'e2e/login'), function () {
  if (!Cypress.env('READY')) {
    tracera.comment('env not ready');
    this.skip();
  }
  cy.visit('/login');
});

步骤

使用 tracera.step 或 cy.traceraStep:调用 tracera.step(title, fn) / cy.traceraStep(title, fn),在类方法上使用装饰器 @tracera.step("…"),或 tracera.step("…")(fn)。装饰器标题中的 {name} / {0} 从方法参数填入;也可以传入返回标题的函数。调用形式不会填充 {name} / {0}——请传入已拼好的标题字符串。异步代码走 Cypress 命令队列。 在 import "@tracera/cypress/support" 之后,标准 beforeEach / afterEach 已仪器化 — 其中的步骤进入结果的 准备 / 清理。套件级钩子(如 before / after)不会上报。

import { tracera } from '@tracera/cypress/runtime';

beforeEach(() => {
  tracera.step('open shop', () => {
    return cy.visit('/shop');
  });
});

it('checkout', () => {
  tracera.testCase(10, 'e2e/checkout');
  tracera.step('add to cart', () => {
    return cy.get('[data-testid=add]').click();
  });
});

afterEach(() => {
  tracera.step('cleanup', () => {
    // …
  });
});

方法上的装饰器:

import { tracera } from '@tracera/cypress/runtime';

class Cart {
  @tracera.step('add {item}')
  async addToCart(item: string) {
    // …
  }
}

注释、错误与附件

评论、错误与附件:自动化测试适配器。注册插件后,失败截图会加到结果上。

import { tracera } from '@tracera/cypress/runtime';

it('login', () => {
  tracera.testCase(42, 'e2e/login');
  tracera.comment('result-level note');
  tracera.error('result-level error text');

  tracera.step('open login', () => {
    return cy.visit('/login').then(() => {
      tracera.comment('landed on login');
      tracera.attachment({
        fileName: 'suite-log.txt',
        mimeType: 'text/plain',
        data: 'finished login flow',
      });
    });
  });
});

参数化测试

import { annotations } from '@tracera/cypress/runtime';

const rows = [
  { id: 42, name: 'e2e/login-ok', path: '/login' },
  { id: 43, name: 'e2e/login-sso', path: '/login/sso' },
];

for (const row of rows) {
  it(row.name, annotations(row.id, row.name), () => {
    cy.visit(row.path);
  });
}

或在测试中调用 tracera.testCase(row.id, row.name),代替 annotations。