mcpField
Q
qa-regression

qa-regression

github.com/moizibnyousaf测试与质量1.2k125 次安装5 周前更新
代码仓库

关于 qa-regression

qa-regression 是使用 Playwright 构建和运行自动化回归测试的技能。它将可复用测试和辅助函数组织成测试套件,并提供 CI 集成及测试维护指导。

主要功能

  1. 01编写可复用的 Playwright 测试
  2. 02组合回归测试套件
  3. 03共享身份验证和数据辅助函数
  4. 04并行运行或使用 UI 模式
  5. 05配置 CI 回归测试

适用场景

  1. 01检查登录和注销流程
  2. 02验证仪表板加载
  3. 03测试用户创建行为
  4. 04在 CI 中运行回归测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/moizibnyousaf/ai-agent-skills --skill qa-regression

安装后在 Claude Code 中输入/qa-regression确认已加载。

详细介绍

QA 回归测试

使用 Playwright 构建并运行自动化回归测试。每个测试都是一种可复用的技能,可组合成完整的测试套件。

设置

npm init -y
npm install playwright @playwright/test
npx playwright install

测试结构

在 tests/ 文件夹中创建测试:

tests/
├── auth/
│   ├── login.spec.ts
│   └── logout.spec.ts
├── dashboard/
│   └── load.spec.ts
├── users/
│   ├── create.spec.ts
│   └── delete.spec.ts
└── regression.spec.ts   # Full suite

常用测试技能

登录测试
// tests/auth/login.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Login Flow', () => {
  test('should login with valid credentials', async ({ page }) => {
    await page.goto('/login');

    await page.fill('[data-testid="email"]', process.env.TEST_EMAIL!);
    await page.fill('[data-testid="password"]', process.env.TEST_PASSWORD!);
    await page.click('[data-testid="submit"]');

    // Verify redirect to dashboard
    await expect(page).toHaveURL(/dashboard/);
    await expect(page.locator('[data-testid="user-menu"]')).toBeVisible();
  });

  test('should show error for invalid credentials', async ({ page }) => {
    await page.goto('/login');

    await page.fill('[data-testid="email"]', '[email protected]');
    await page.fill('[data-testid="password"]', 'wrongpassword');
    await page.click('[data-testid="submit"]');

    await expect(page.locator('[data-testid="error-message"]')).toBeVisible();
  });
});
仪表盘加载测试
// tests/dashboard/load.spec.ts
import { test, expect } from '@playwright/test';
import { login } from '../helpers/auth';

test.describe('Dashboard', () => {
  test.beforeEach(async ({ page }) => {
    await login(page);
  });

  test('should load dashboard within 3 seconds', async ({ page }) => {
    const start = Date.now();
    await page.goto('/dashboard');
    await page.waitForSelector('[data-testid="dashboard-content"]');
    const loadTime = Date.now() - start;

    expect(loadTime).toBeLessThan(3000);
  });

  test('should display all widgets', async ({ page }) => {
    await page.goto('/dashboard');

    await expect(page.locator('[data-testid="stats-widget"]')).toBeVisible();
    await expect(page.locator('[data-testid="chart-widget"]')).toBeVisible();
    await expect(page.locator('[data-testid="activity-widget"]')).toBeVisible();
  });

  test('should refresh data on button click', async ({ page }) => {
    await page.goto('/dashboard');

    const initialValue = await page.locator('[data-testid="last-updated"]').textContent();
    await page.click('[data-testid="refresh-button"]');
    await page.waitForTimeout(1000);
    const newValue = await page.locator('[data-testid="last-updated"]').textContent();

    expect(newValue).not.toBe(initialValue);
  });
});
创建用户测试
// tests/users/create.spec.ts
import { test, expect } from '@playwright/test';
import { login } from '../helpers/auth';
import { generateTestUser, deleteTestUser } from '../helpers/users';

test.describe('User Creation', () => {
  let testUser: { email: string; name: string };

  test.beforeEach(async ({ page }) => {
    await login(page);
    testUser = generateTestUser();
  });

  test.afterEach(async () => {
    // Cleanup
    await deleteTestUser(testUser.email);
  });

  test('should create new user successfully', async ({ page }) => {
    await page.goto('/users/new');

    await page.fill('[data-testid="user-name"]', testUser.name);
    await page.fill('[data-testid="user-email"]', testUser.email);
    await page.selectOption('[data-testid="user-role"]', 'member');
    await page.click('[data-testid="create-user-btn"]');

    // Verify success
    await expect(page.locator('[data-testid="success-toast"]')).toBeVisible();
    await expect(page).toHaveURL(/users/);

    // Verify user appears in list
    await expect(page.locator(`text=${testUser.email}`)).toBeVisible();
  });

  test('should validate required fields', async ({ page }) => {
    await page.goto('/users/new');
    await page.click('[data-testid="create-user-btn"]');

    await expect(page.locator('[data-testid="name-error"]')).toBeVisible();
    await expect(page.locator('[data-testid="email-error"]')).toBeVisible();
  });
});

共享辅助工具

// tests/helpers/auth.ts
import { Page } from '@playwright/test';

export async function login(page: Page) {
  await page.goto('/login');
  await page.fill('[data-testid="email"]', process.env.TEST_EMAIL!);
  await page.fill('[data-testid="password"]', process.env.TEST_PASSWORD!);
  await page.click('[data-testid="submit"]');
  await page.waitForURL(/dashboard/);
}

export async function logout(page: Page) {
  await page.click('[data-testid="user-menu"]');
  await page.click('[data-testid="logout"]');
  await page.waitForURL(/login/);
}
// tests/helpers/users.ts
export function generateTestUser() {
  const id = Date.now();
  return {
    name: `Test User ${id}`,
    email: `test-${id}@example.com`,
  };
}

export async function deleteTestUser(email: string) {
  // API call to cleanup test user
  await fetch(`${process.env.API_URL}/admin/users`, {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${process.env.ADMIN_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ email }),
  });
}

完整回归测试套件

// tests/regression.spec.ts
import { test } from '@playwright/test';

// Import all test suites
import './auth/login.spec';
import './auth/logout.spec';
import './dashboard/load.spec';
import './users/create.spec';
import './users/delete.spec';

test.describe('Full Regression Suite', () => {
  // Tests run in order defined above
});

Playwright 配置

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: [
    ['html'],
    ['json', { outputFile: 'test-results.json' }],
  ],
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

运行测试

# Run all tests
npx playwright test

# Run specific test file
npx playwright test tests/auth/login.spec.ts

# Run tests with UI
npx playwright test --ui

# Run in headed mode (see browser)
npx playwright test --headed

# Generate report
npx playwright show-report

CI 集成

# .github/workflows/regression.yml
name: Regression Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 6 * * *'  # Daily at 6 AM

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright
        run: npx playwright install --with-deps

      - name: Run tests
        run: npx playwright test
        env:
          BASE_URL: ${{ secrets.STAGING_URL }}
          TEST_EMAIL: ${{ secrets.TEST_EMAIL }}
          TEST_PASSWORD: ${{ secrets.TEST_PASSWORD }}

      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: playwright-report
          path: playwright-report/

最佳实践

  1. 使用 data-testid 属性 - 比 CSS 选择器更稳定
  2. 清理测试数据 - 始终删除创建的数据
  3. 避免硬编码等待 - 使用 waitForSelector,而非 waitForTimeout
  4. 并行运行 - 在 CI 中更快地获得反馈
  5. 失败时截图 - 更便于调试
  6. 环境变量 - 切勿提交凭据

快捷命令

任务命令
运行全部测试npx playwright test
运行单个文件npx playwright test login.spec.ts
调试模式npx playwright test --debug
UI 模式npx playwright test --ui
更新快照npx playwright test --update-snapshots

评论

支持 Markdown