Token导航 LogoToken导航TokenDH.com
研究检索操作浏览器github未标认证来源可访问许可证需确认审计通过

ai-qa-review艾卡评论

Agent Skill

ai-qa-review 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

374

周安装

15

GitHub Stars

4

下载量

121
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:ai-qa-review(艾卡评论)
来源仓库:https://github.com/petrkindlmann/qa-skills
仓库路径:skills/ai-qa-review
安装命令:
npx skills add https://github.com/petrkindlmann/qa-skills --skill ai-qa-review
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/petrkindlmann/qa-skills --skill ai-qa-review

简介

AI QA 评审技能依据项目特定质量标准,对测试代码与应用代码的可维护性提供专业反馈。

  • 支持 Jest、Playwright 等多种测试框架的惯例适配,提供命名规范与断言风格建议。
  • 可执行 PR 级细粒度审查或全量审计模式,灵活匹配不同阶段的质控强度要求。
  • 使用前需创建 .agents/qa-project-context.md 配置文件定义项目专属质量基线。
  • 建议结合 CI 流水线集成自动化评审门禁,阻断不符合规范的代码合入主干分支。

SKILL.md

Before starting: Check for .agents/qa-project-context.md in the project root. It contains test framework conventions, naming patterns, and project-specific quality standards that calibrate review feedback.


Discovery Questions

  1. Review scope: Reviewing test code for quality, application code for testability, or both? Each triggers different analysis patterns.
  2. Framework conventions: What test framework (Jest, Vitest, Playwright, pytest)? Conventions differ -- describe/it nesting, fixture usage, assertion style.
  3. PR review or batch audit? A PR review focuses on changed files. A batch audit scans the entire test suite for systemic patterns.
  4. Existing quality standards: Does the team have documented test conventions? Check for .eslintrc test rules, CONTRIBUTING.md test guidelines, or a test style guide.
  5. Known pain points: Are there recurring problems -- flaky tests, slow suites, unclear failures? These prioritize which smells to focus on first.

Core Principles

  1. Test code is production code. Apply the same quality standards: readability, maintainability, single responsibility. Test code that is hard to read is hard to trust.
  2. Testability review prevents test debt. Reviewing application code for testability catches design problems before they force awkward test workarounds. If code is hard to test, it is usually hard to maintain.
  3. Codify patterns, not just knowledge. Turn recurring review feedback into lint rules, custom ESLint plugins, or shared fixtures. Reviews that repeat the same feedback indicate missing automation.
  4. Smells are symptoms, not verdicts. A test smell indicates a potential problem. Context determines whether it is actually harmful. A long test for a complex workflow may be appropriate. A mock-heavy test for a boundary may be correct.
  5. Actionable feedback only. Every review comment must include what is wrong, why it matters, and how to fix it. "This test is bad" is not actionable. "This test uses sleep-based waiting which causes flakiness -- replace with explicit wait condition" is.

Test Smell Buckets

Each smell is categorized by the dimension it affects. Each links to a specific review action.

Readability Smells

Problems that make tests hard to understand at a glance.

Obscure Setup

What it looks like: 30+ lines of object construction with irrelevant fields drowning the test intent. The reader cannot tell which fields matter for the assertion.

Fix: Extract to factories. Only test-relevant data should appear in the test body: buildOrder({items: [buildItem({weight: 2.5, quantity: 2})]}) instead of constructing full user/product/order objects inline.

Review action: Request factory extraction.

Mystery Guest

What it looks like: loadFixture('report.json') -- the test depends on external data the reader cannot see. They must open another file to understand the assertion.

Fix: Inline the test-relevant data or use descriptively named fixtures. The reader should understand the test without opening other files.

Review action: Request inline data or descriptive fixture names.

Duplicate Assertions

What it looks like: Multiple tests assert the same behavior with varying specificity (toBe('Alice'), toHaveProperty('name'), toBeDefined()). Three tests, one behavior.

Review action: Request consolidation. Keep the most specific assertion. Redundant tests increase maintenance cost without increasing confidence.


Reliability Smells

Problems that cause tests to fail intermittently or in unexpected environments.

Sleep-Based Waiting

What it looks like: setTimeout, sleep(), waitForTimeout() used for synchronization.

// SMELL: Slow on fast machines, flaky on slow ones
it('should show notification after save', async () => {
  await page.click('#save');
  await page.waitForTimeout(3000);
  expect(await page.isVisible('.notification')).toBe(true);
});

// FIX: Wait for the specific condition
it('should show notification after save', async () => {
  await page.getByRole('button', { name: 'Save' }).click();
  await expect(page.getByRole('alert')).toBeVisible();
});

Review action: Reject. Sleep-based waiting is never acceptable. Require explicit wait conditions.

Order Dependency

What it looks like: Tests pass when run together but fail in isolation or different order.

// SMELL: Test B depends on Test A's side effects
describe('user management', () => {
  it('A: should create a user', async () => {
    await api.post('/users', { name: 'Alice' });
  });
  it('B: should list users', async () => {
    const users = await api.get('/users');
    expect(users).toContainEqual({ name: 'Alice' }); // Fails if A didn't run first
  });
});

// FIX: Each test sets up its own state
describe('user management', () => {
  it('should create a user', async () => {
    const response = await api.post('/users', { name: 'Alice' });
    expect(response.status).toBe(201);
  });
  it('should list users including recently created', async () => {
    await api.post('/users', { name: 'Bob' }); // Own setup
    const users = await api.get('/users');
    expect(users).toContainEqual({ name: 'Bob' });
  });
});

Review action: Request data isolation. Each test must create its own preconditions.

External Service Coupling

What it looks like: Tests call real external APIs (payment gateways, email providers, third-party services).

// SMELL: Fails when Stripe is down, rate-limited, or returns different data
it('should process payment', async () => {
  const result = await stripe.charges.create({ amount: 2000, currency: 'usd' });
  expect(result.status).toBe('succeeded');
});

// FIX: Mock the boundary
it('should process payment', async () => {
  const mockStripe = { charges: { create: vi.fn().mockResolvedValue({ status: 'succeeded' }) } };
  const service = new PaymentService(mockStripe);
  const result = await service.charge(2000, 'usd');
  expect(result.status).toBe('succeeded');
});

Review action: Request mock or fake at the service boundary. External calls belong in integration/contract tests, not unit tests.


Diagnostic Smells

Problems that make test failures hard to understand and debug.

Weak Assertion Messages

What it looks like: Assertion fails with no context about what was expected or why.

// SMELL: Failure message: "Expected false to be true" -- useless
it('should validate the form', () => {
  expect(isValid(form)).toBe(true);
});

// FIX: Use specific assertions that produce clear failure messages
it('should accept form with valid email and non-empty name', () => {
  const result = validate(form);
  expect(result.isValid).toBe(true);
  expect(result.errors).toEqual([]);
  // Failure: "Expected errors to equal [] but received [{ field: 'email', message: 'invalid format' }]"
});

Review action: Request stronger assertions with diagnostic value. The failure message should explain the problem without reading the test source.

Multiple Failure Causes Per Test

What it looks like: A single test covers multiple independent behaviors. When it fails, you do not know which behavior broke.

// SMELL: If this fails, is it the creation, the update, or the deletion?
it('should handle user lifecycle', async () => {
  const user = await service.create({ name: 'Alice' });
  expect(user.id).toBeDefined();

  await service.update(user.id, { name: 'Bob' });
  const updated = await service.get(user.id);
  expect(updated.name).toBe('Bob');

  await service.delete(user.id);
  await expect(service.get(user.id)).rejects.toThrow(NotFoundError);
});

// FIX: One behavior per test
it('should create user with generated id', async () => {
  const user = await service.create({ name: 'Alice' });
  expect(user.id).toBeDefined();
});

it('should update user name', async () => {
  const user = await service.create({ name: 'Alice' });
  await service.update(user.id, { name: 'Bob' });
  expect((await service.get(user.id)).name).toBe('Bob');
});

it('should delete user so they cannot be retrieved', async () => {
  const user = await service.create({ name: 'Alice' });
  await service.delete(user.id);
  await expect(service.get(user.id)).rejects.toThrow(NotFoundError);
});

Review action: Request test splitting. Each test should have one reason to fail.


Design Smells

Problems in test architecture that increase maintenance cost.

Conditional Test Logic

What it looks like: if/else, switch, or ternaries inside test bodies.

// SMELL: Test logic that can take different paths is itself untested
it('should handle all user roles', () => {
  for (const role of ['admin', 'user', 'guest']) {
    const result = getPermissions(role);
    if (role === 'admin') {
      expect(result).toContain('delete');
    } else if (role === 'user') {
      expect(result).toContain('read');
      expect(result).not.toContain('delete');
    } else {
      expect(result).toEqual(['read']);
    }
  }
});

// FIX: Use parameterized tests (test.each / it.each)
it.each([
  ['admin', ['read', 'write', 'delete']],
  ['user', ['read', 'write']],
  ['guest', ['read']],
])('role "%s" should have permissions %j', (role, expected) => {
  expect(getPermissions(role)).toEqual(expected);
});

Review action: Request parameterized tests. Conditional logic in tests hides which cases are actually verified.

Giant Fixtures

What it looks like: A beforeEach or fixture that sets up 20+ objects for every test, even though each test uses 2-3 of them.

// SMELL: Every test pays the setup cost for data it doesn't use
beforeEach(async () => {
  await createUser(pool, { id: 'u1', role: 'admin' });
  await createUser(pool, { id: 'u2', role: 'user' });
  await createUser(pool, { id: 'u3', role: 'guest' });
  await createProduct(pool, { id: 'p1', stock: 100 });
  await createProduct(pool, { id: 'p2', stock: 0 });
  await createOrder(pool, { id: 'o1', userId: 'u2' });
  await createOrder(pool, { id: 'o2', userId: 'u2' });
  // ... 15 more objects
});

// FIX: Each test creates only what it needs
it('should prevent guest from deleting products', async () => {
  const guest = await createUser(pool, { role: 'guest' });
  const product = await createProduct(pool, { stock: 50 });
  await expect(productService.delete(product.id, guest.id)).rejects.toThrow(ForbiddenError);
});

Review action: Request inline setup. Move shared setup to factories, not monolithic beforeEach blocks.

Over-Mocking

What it looks like: Every collaborator is mocked, including simple value objects and pure functions.

// SMELL: Mocking the thing you are testing
it('should format price', () => {
  const mockFormatter = vi.fn().mockReturnValue('$29.99');
  const result = mockFormatter(29.99);
  expect(mockFormatter).toHaveBeenCalledWith(29.99);
  expect(result).toBe('$29.99');
  // This test verifies nothing about the real formatPrice function
});

// FIX: Only mock external boundaries (network, DB, filesystem, time)
it('should format price with currency symbol', () => {
  expect(formatPrice(29.99, 'USD')).toBe('$29.99');
  expect(formatPrice(29.99, 'EUR')).toBe('29,99 EUR');
});

Review action: Request removal of unnecessary mocks. Mock boundaries, not internals.


Coverage Smells

Problems that leave gaps in what is verified.

Happy Path Only

What it looks like: Every test provides valid input and expects success. No error paths tested.

// SMELL: What happens with invalid input? Empty input? Null? Boundary values?
describe('calculateDiscount', () => {
  it('should apply 10% discount', () => {
    expect(calculateDiscount(100, 0.1)).toBe(90);
  });
  it('should apply 20% discount', () => {
    expect(calculateDiscount(200, 0.2)).toBe(160);
  });
});

// FIX: Add boundary, negative, and error cases
describe('calculateDiscount', () => {
  it('should apply percentage discount', () => {
    expect(calculateDiscount(100, 0.1)).toBe(90);
  });
  it('should handle zero discount', () => {
    expect(calculateDiscount(100, 0)).toBe(100);
  });
  it('should handle 100% discount', () => {
    expect(calculateDiscount(100, 1.0)).toBe(0);
  });
  it('should reject negative discount', () => {
    expect(() => calculateDiscount(100, -0.1)).toThrow('Discount must be between 0 and 1');
  });
  it('should reject discount over 100%', () => {
    expect(() => calculateDiscount(100, 1.5)).toThrow('Discount must be between 0 and 1');
  });
  it('should handle zero price', () => {
    expect(calculateDiscount(0, 0.1)).toBe(0);
  });
});

Review action: Request missing scenarios. Use the BOUNDARY framework: Boundary values, Null/empty, Duplicates, Ordering, Range limits.

Missing Boundary Cases

What it looks like: Tests for "normal" values (5 items) but not for 0, 1, max, or max+1. Use it.each to cover boundaries explicitly: empty collection, single item, exact page size, one over, large set.

Review action: Request boundary tests. Every numeric parameter, string length, and collection size has boundaries to test.

Missing Error/Negative Cases

What it looks like: No tests for what happens when things go wrong -- network failures, invalid input, permission denied, concurrent modification.

Review action: For each happy path test, ask: "What is the corresponding failure mode?" Request tests for the failure.


Testability Analysis

When reviewing application code, assess whether it is structured for testability.

Dependency Injection

Flag classes that instantiate dependencies directly (new PostgresDatabase(), new StripeClient() inside methods). Suggest constructor injection so tests can substitute mocks/fakes.

// HARD TO TEST                          // TESTABLE
class OrderService {                     class OrderService {
  async create(data: OrderInput) {         constructor(
    const db = new PostgresDB();             private readonly db: Database,
    const email = new SendGrid();            private readonly email: EmailClient,
  }                                        ) {}
}                                        }

Side Effect Isolation

Flag functions that mix pure calculation with I/O (email, logging, analytics). Suggest extracting the calculation as a pure function, then calling it from the side-effectful orchestrator.

Pure Function Extraction

Look for validation, transformation, and business rules buried inside request handlers. If logic is inline in app.post('/api/orders',...), it cannot be unit-tested without spinning up an HTTP server. Extract it as a standalone function.

Interface Segregation

Flag classes that depend on broad interfaces (entire PrismaClient) when they only use 2-3 methods. Suggest defining a narrow interface with only the methods actually used, making test doubles trivial to implement.


Review Workflow

PR Review Checklist

For each test file in a PR, check systematically:

## Test Quality Review

### Readability
- [ ] Can I understand what each test verifies in under 10 seconds?
- [ ] Is setup minimal and test-relevant?
- [ ] Are test names descriptive: "should [behavior] when [condition]"?

### Reliability
- [ ] No sleep/waitForTimeout/setTimeout for synchronization?
- [ ] No shared mutable state between tests?
- [ ] No dependency on test execution order?
- [ ] No calls to real external services?

### Diagnostic Value
- [ ] Will failures produce messages that identify the problem?
- [ ] Does each test have one reason to fail?
- [ ] Are assertions specific (not toBeTruthy/toBeDefined)?

### Design
- [ ] No conditional logic (if/else/switch) in test bodies?
- [ ] Fixtures/setup proportional to what each test needs?
- [ ] Mocking limited to external boundaries?
- [ ] Parameterized tests used for data-driven scenarios?

### Coverage
- [ ] Happy path AND error/negative paths tested?
- [ ] Boundary values tested (0, 1, max, max+1)?
- [ ] Edge cases: empty, null, duplicate, concurrent?

Batch Audit Process

For a full test suite audit:

  1. Quantify: Count tests by type (unit/integration/E2E), framework, and directory.
  2. Sample: Review 10-20% of test files, prioritizing the largest and most recently changed.
  3. Pattern: Identify the 3-5 most common smells across the sample.
  4. Prioritize: Rank by impact: reliability smells > diagnostic smells > design smells > readability smells.
  5. Automate: For each common smell, determine if an ESLint rule or custom plugin can catch it automatically.
  6. Report: Document findings with specific examples, suggested fixes, and estimated effort.

Prompt Templates

Three prompt patterns for AI-assisted review:

  1. Review test quality: "Check this test file for readability, reliability, diagnostics, design, and coverage smells. For each issue: name the smell, cite the line, explain why it matters, and provide a fix."
  2. Identify coverage gaps: "Given this application code and its existing tests, identify missing scenarios across happy path, error handling, boundaries, edge cases, concurrency, and security. Prioritize as P0/P1/P2."
  3. Testability improvements: "Review this application code for hard-coded dependencies, mixed side effects, extractable pure functions, and overly broad interfaces. Show current vs. refactored code."

Anti-Patterns

Reviewing test code with production code standards only. Test code has additional quality dimensions (reliability, diagnostics, coverage) that production code linters do not check. Apply the smell buckets above, not just "clean code" principles.

Flagging every smell without context. A 50-line test for a complex state machine is not obscure setup -- it is necessary complexity. Evaluate smells against the behavior being tested.

Suggesting mocks for everything. Over-mocking is a smell. Do not recommend mocking pure functions, value objects, or fast in-process collaborators. Mock boundaries: network, database, filesystem, clock.

Focusing on coverage percentage over coverage quality. 95% line coverage with only happy-path tests is worse than 75% coverage that includes error paths and boundaries. Review what is asserted, not just what is executed.

Reviewing without running. Static analysis misses runtime issues. Run the tests. Check for flakiness (run 3x). Check execution time. A passing test suite that takes 20 minutes has a performance smell.

One-time review without follow-up. Test quality degrades over time. Establish recurring review cadence or automated quality gates that catch regression.


Done When

  • All five smell dimensions reviewed: coverage gaps, assertion quality, test independence, maintainability, and anti-patterns
  • Findings report created with severity ratings (high/medium/low) for each identified issue
  • High-severity issues have actionable remediation steps, not just descriptions of the problem
  • Review findings fed back into the team's Definition of Done to prevent recurrence

Related Skills

  • unit-testing -- Framework-specific patterns (Jest, Vitest, pytest) that inform what "good" looks like for each framework.
  • shift-left-testing -- Pre-commit hooks and IDE integration that catch test smells before review.
  • coverage-analysis -- Interpreting coverage reports to find meaningful gaps, not just percentage targets.
  • ai-test-generation -- Generated tests need review too. Apply these smell checks to AI-generated test code.
  • test-reliability -- Reliability smells (sleep-based waits, order dependency) overlap with flaky test patterns.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

34.29%
按下载量换算41

Claude

32.54%
按下载量换算39

Cursor

19.63%
按下载量换算24

Gemini CLI

9.21%
按下载量换算11

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills