Test Specialist
JavaScript/TypeScript 测试专家,提供系统化测试方法、调试技巧和覆盖率分析工具,覆盖单元测试、集成测试到 E2E 测试全流程。
Install 安装
curl -sSL https://updating.cc/skills/cocoloop/qa-test-specialist/SKILL.md -o ~/.agents/skills/cocoloop__qa-test-specialist/SKILL.mdSKILL.md Preview 技能内容预览
---
name: test-specialist
description: This skill should be used when writing test cases, fixing bugs, analyzing code for potential issues, or improving test coverage for JavaScript/TypeScript applications. Use this for unit tests, integration tests, end-to-end tests, debugging runtime errors, logic bugs, performance issues, security vulnerabilities, and systematic code analysis.
---
# Test Specialist
## Overview
Apply systematic testing methodologies and debugging techniques to JavaScript/TypeScript applications. This skill provides comprehensive testing strategies, bug analysis frameworks, and automated tools for identifying coverage gaps and untested code.
## Core Capabilities
### 1. Writing Test Cases
Write comprehensive tests covering unit, integration, and end-to-end scenarios.
#### Unit Testing Approach
Structure tests using the AAA pattern (Arrange-Act-Assert):
```typescript
describe('ExpenseCalculator', () => {
describe('calculateTotal', () => {
test('sums expense amounts correctly', () => {
// Arrange
const expenses = [
{ amount: 100, category: 'food' },
{ amount: 50, category: 'transport' },
{ amount: 25, category: 'entertainment' }
];
// Act
const total = calculateTotal(expenses);
// Assert
expect(total).toBe(175);
});
test('handles empty expense list', () => {
expect(calculateTotal([])).toBe(0);
});
test('handles negative amounts', () => {
const expenses = [
{ amount: 100, category: 'food' },
{ amount: -50, category: 'refund' }
];
expect(calculateTotal(expenses)).toBe(50);
});
});
});
```
**Key principles:**
- Test one behavior per test
- Cover happy path, edge cases, and error conditions
- Use descriptive test names that explain the scenario
- Keep tests independent and isolated
#### Integration Testing Approach
Test how components work together, including database, API, and service interactions:
```typescript
describe('ExpenseAPI Integration', () => {
beforeAll(async () => {
await database.connect(TEST_DB_URL);
});
afterAll(async () => {
await database.disconnect();
});
beforeEach(async () => {
await database.clear();
await seedTestData();
});
test('POST /expenses creates expense and updates total', async () => {
const response = await request(app)
.post('/api/expenses')
.send({
amount: 50,
category: 'food',
description: 'Lunch'
})
.expect(201);
expect(response.body).toMatchObject({
id: expect.any(Number),
amount: 50,
category: 'food'
});
// Verify database state
const total = await getTotalExpenses();
expect(total).toBe(50);
});
});
```
#### End-to-End Testing Approach
Test complete user workflows using tools like Playwright or Cypress:
```typescript
test('user can track expense from start to finish', async ({ page }) => {
// Navigate to app
await page.goto('/');
// Add new expense
await page.click('[data-testid="add-expense-btn"]');
await page.fill('[data-testid="amount"]', '50.00');
await page.selectOption('[data-testid="category"]', 'food');
await page.fill('[data-testid="description"]', 'Lunch');
await page.click('[data-testid="submit"]');
// Verify expense appears in list
await expect(page.locator('[data-testid="expense-item"]')).toContainText('Lunch');
await expect(page.locator('[data-testid="total"]')).toContainText('$50.00');
});
```
### 2. Systematic Bug Analysis
Apply structured debugging methodology to identify and fix issues.
#### Five-Step Analysis Process
1. **Reproduction**: Reliably reproduce the bug
- Document exact steps to trigger
- Identify required environment/state
- Note expected vs actual behavior
2. **Isolation**: Narrow down the problem
- Binary search through code path
- Create minimal reproduction case
- Remove unrelated dependencies
3. **Root Cause Analysis**: Determine underlying cause
- Trace execution flow
- Check assumptions and preconditions
- Review recent changes (git blame)
4. **Fix Implementation**: Implement solution
- Write failing test first (TDD)
- Implement the fix
- Verify test passes
5. **Validation**: Ensure completeness
- Run full test suite
- Test edge cases
- Verify no regressions
#### Common Bug Patterns
**Race Conditions:**
```typescript
// Test concurrent operations
test('handles concurrent updates correctly', async () => {
const promises = Array.from({ length: 100 }, () =>
incrementExpenseCount()
);
await Promise.all(promises);
expect(getExpenseCount()).toBe(100);
});
```
**Null/Undefined Errors:**
```typescript
// Test null safety
test.each([null, undefined, '', 0, false])
('handles invalid input: %p', (input) => {
expect(() => processExpense(input)).toThrow('Invalid expense');
});
```
**Off-by-One Errors:**
```typescript
// Test boundaries explicitly
describe('pagination', () => {
test('handles empty list', () => {
expect(paginate([], 1, 10)).toEqual([]);
});
test('handles single item', () => {
expect(paginate([item], 1, 10)).toEqual([item]);
});
test('handles last page with partial items', () => {
const items = Array.from({ length: 25 }, (_, i) => i);
expect(paginate(items, 3, 10)).toHaveLength(5);
});
});
```
### 3. Identifying Potential Issues
Proactively identify issues before they become bugs.
#### Security Vulnerabilities
Test for common security issues:
```typescript
describe('security', () => {
test('prevents SQL injection', async () => {
const malicious = "'; DROP TABLE expenses; --";
await expect(
searchExpenses(malicious)
).resolves.not.toThrow();
});
test('sanitizes XSS in descriptions', () => {
const xss = '<script>alert("xss")</script>';
const expense = createExpense({ description: xss });
expect(expense.description).not.toContain('<script>');
});
test('requires authentication for expense operations', async () => {
await request(app)
.post('/api/expenses')
.send({ amount: 50 })
.expect(401);
});
});
```
#### Performance Issues
Test for performance problems:
```typescript
test('processes large expense list efficiently', () => {
const largeList = Array.from({ length: 10000 }, (_, i) => ({
amount: i,
category: 'test'
}));
const start = performance.now();
const total = calculateTotal(largeList);
const duration = performance.now() - start;
expect(duration).toBeLessThan(100); // Should complete in <100ms
expect(total).toBe(49995000);
});
```
#### Logic Errors
Use parameterized tests to catch edge cases:
```typescript
test.each([
// [input, expected, description]
[[10, 20, 30], 60, 'normal positive values'],
[[0, 0, 0], 0, 'all zeros'],
[[-10, 20, -5], 5, 'mixed positive and negative'],
[[0.1, 0.2], 0.3, 'decimal precision'],
[[Number.MAX_SAFE_INTEGER], Number.MAX_SAFE_INTEGER, 'large numbers'],
])('calculateTotal(%p) = %p (%s)', (amounts, expected, description) => {
const expenses = amounts.map(amount => ({ amount, category: 'test' }));
expect(calculateTotal(expenses)).toBeCloseTo(expected);
});
```
### 4. Test Coverage Analysis
Use automated tools to identify gaps in test coverage.
#### Finding Untested Code
Run the provided script to identify source files without tests:
```bash
python3 scripts/find_untested_code.py src
```
The script will:
- Scan source directory for all code files
- Identify which files lack corresponding test files
- Categorize untested files by type (components, services, utils, etc.)
- Prioritize files that need testing most
**Interpretation:**
- **API/Services**: High priority - test business logic and data operations
- **Models**: High priority - test data validation and transformations
- **Hooks**: Medium priority - test stateful behavior
- **Components**: Medium priority - test complex UI logic
- **Utils**: Low priori