Best for
- Writing new code (TDD approach)
- Adding tests to existing code
- Improving test coverage
VoDaiLocz/kilo-kit-mcp/skills/kilo-kit/quality/testing/SKILL.md
Comprehensive testing skill covering unit, integration, and e2e testing with TDD. Use when writing tests, improving coverage, or setting up testing infrastructure. Keywords: test, TDD, unit test, integration, e2e, coverage, mock, jest, vitest
Decision brief
Philosophy: If it's not tested, it's broken. You just don't know it yet.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/VoDaiLocz/kilo-kit-mcp --skill "skills/kilo-kit/quality/testing"Inspect the Agent Skill "testing-strategy" from https://github.com/VoDaiLocz/kilo-kit-mcp/blob/29dff82378b9f298ecb7141d2dd59c6bd6bfb3ad/skills/kilo-kit/quality/testing/SKILL.md at commit 29dff82378b9f298ecb7141d2dd59c6bd6bfb3ad. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Run test → Should FAIL (RED)
Run test → Should FAIL (RED)
Run test → Should PASS (GREEN)
Run test → Should still PASS
Use this skill when: - Writing new code (TDD approach) - Adding tests to existing code - Improving test coverage - Fixing flaky tests - Setting up testing infrastructure - Debugging test failures
Permission review
The documentation includes network, browsing, or remote request actions.
const config = { API_URL: 'http://test-api.com' };Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 96/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 24 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Philosophy: If it's not tested, it's broken. You just don't know it yet.
Use this skill when:
Do NOT use this skill when:
╱╲
╱ ╲
╱ E2E╲ Few, slow, expensive
╱──────╲ Full system tests
╱ ╲
╱Integration╲ Medium amount
╱────────────╲ Component interaction
╱ ╲
╱ Unit Tests ╲ Many, fast, cheap
╱──────────────────╲ Single unit isolation
// Write the test BEFORE the implementation
describe('calculateDiscount', () => {
it('should apply 10% discount for orders over $100', () => {
// This test will FAIL because function doesn't exist yet
const result = calculateDiscount(150);
expect(result).toBe(135);
});
});
Run test → Should FAIL (RED)
// Write the MINIMUM code to pass the test
function calculateDiscount(amount: number): number {
if (amount > 100) {
return amount * 0.9;
}
return amount;
}
Run test → Should PASS (GREEN)
// Improve code while keeping tests green
const DISCOUNT_THRESHOLD = 100;
const DISCOUNT_RATE = 0.1;
function calculateDiscount(amount: number): number {
if (amount > DISCOUNT_THRESHOLD) {
return amount * (1 - DISCOUNT_RATE);
}
return amount;
}
Run test → Should still PASS
describe('UserService', () => {
describe('createUser', () => {
it('should create user with valid data', async () => {
// Arrange
const userData = { email: '[email protected]', name: 'Test' };
const mockRepo = { create: jest.fn().mockResolvedValue({ id: '1', ...userData }) };
const service = new UserService(mockRepo);
// Act
const result = await service.createUser(userData);
// Assert
expect(result.id).toBe('1');
expect(result.email).toBe(userData.email);
expect(mockRepo.create).toHaveBeenCalledWith(userData);
});
});
});
describe('createUser', () => {
it('should throw on duplicate email', async () => {
// Arrange
const mockRepo = {
findByEmail: jest.fn().mockResolvedValue({ id: 'existing' }),
};
const service = new UserService(mockRepo);
// Act & Assert
await expect(
service.createUser({ email: '[email protected]' })
).rejects.toThrow('Email already registered');
});
});
describe('fetchUserData', () => {
it('should fetch and transform user data', async () => {
// Arrange
const mockApi = {
get: jest.fn().mockResolvedValue({ data: { name: 'John' } }),
};
// Act
const result = await fetchUserData(mockApi, 'user-id');
// Assert
expect(result).toEqual({ name: 'John' });
expect(mockApi.get).toHaveBeenCalledWith('/users/user-id');
});
it('should handle API errors gracefully', async () => {
const mockApi = {
get: jest.fn().mockRejectedValue(new Error('Network error')),
};
await expect(fetchUserData(mockApi, 'user-id'))
.rejects.toThrow('Failed to fetch user');
});
});
// Create mock function
const mockFn = jest.fn();
// Define return value
mockFn.mockReturnValue('static value');
mockFn.mockResolvedValue('async value');
mockFn.mockRejectedValue(new Error('error'));
// Implementation
mockFn.mockImplementation((x) => x * 2);
// Verify calls
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
expect(mockFn).toHaveBeenCalledTimes(3);
// Mock entire module
jest.mock('./database', () => ({
connect: jest.fn(),
query: jest.fn(),
}));
// Mock with factory
jest.mock('./config', () => ({
get: (key: string) => {
const config = { API_URL: 'http://test-api.com' };
return config[key];
},
}));
// Spy on existing method
const spy = jest.spyOn(userService, 'sendEmail');
// Call the code
await userService.createUser({ email: '[email protected]' });
// Verify the spy
expect(spy).toHaveBeenCalled();
// Restore original
spy.mockRestore();
describe('POST /users', () => {
let app: Express;
let db: Database;
beforeAll(async () => {
db = await Database.connect(TEST_DB_URL);
app = createApp(db);
});
afterAll(async () => {
await db.disconnect();
});
beforeEach(async () => {
await db.clear('users');
});
it('should create user and return 201', async () => {
const response = await request(app)
.post('/users')
.send({ email: '[email protected]', password: 'Password123!' })
.expect(201);
expect(response.body.email).toBe('[email protected]');
expect(response.body.password).toBeUndefined();
// Verify in database
const user = await db.users.findOne({ email: '[email protected]' });
expect(user).toBeDefined();
});
it('should return 400 for invalid email', async () => {
const response = await request(app)
.post('/users')
.send({ email: 'invalid', password: 'Password123!' })
.expect(400);
expect(response.body.errors).toContainEqual(
expect.objectContaining({ field: 'email' })
);
});
});
describe('UserRepository', () => {
let db: Database;
let repo: UserRepository;
beforeAll(async () => {
db = await Database.connect(TEST_DB_URL);
repo = new UserRepository(db);
});
beforeEach(async () => {
await db.clear('users');
await db.seed('users', testUsers);
});
it('should find user by email', async () => {
const user = await repo.findByEmail('[email protected]');
expect(user?.name).toBe('John Doe');
});
it('should return null for non-existent email', async () => {
const user = await repo.findByEmail('[email protected]');
expect(user).toBeNull();
});
});
import { test, expect } from '@playwright/test';
test.describe('User Registration', () => {
test('should complete registration flow', async ({ page }) => {
// Navigate to registration
await page.goto('/register');
// Fill form
await page.fill('[data-testid="email"]', '[email protected]');
await page.fill('[data-testid="password"]', 'SecurePassword123!');
await page.fill('[data-testid="name"]', 'New User');
// Submit
await page.click('[data-testid="submit"]');
// Verify redirect to dashboard
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('[data-testid="welcome-message"]'))
.toContainText('Welcome, New User');
});
test('should show validation errors', async ({ page }) => {
await page.goto('/register');
await page.fill('[data-testid="email"]', 'invalid-email');
await page.click('[data-testid="submit"]');
await expect(page.locator('[data-testid="email-error"]'))
.toBeVisible();
});
});
coverage_targets:
statements: 80%
branches: 80%
functions: 80%
lines: 80%
priority_areas:
critical: 95%+ # Auth, payments, core business logic
high: 85%+ # API endpoints, services
medium: 70%+ # Utilities, helpers
low: 50%+ # UI components, config
// jest.config.js
module.exports = {
collectCoverage: true,
coverageDirectory: 'coverage',
coverageReporters: ['text', 'lcov', 'html'],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!src/**/*.d.ts',
'!src/**/*.stories.{ts,tsx}',
'!src/test/**/*',
],
};
| Cause | Symptom | Solution |
|---|---|---|
| Race conditions | Fails randomly | Add proper waits, use async/await correctly |
| Shared state | Fails when run together | Isolate test data, proper cleanup |
| Time-dependent | Fails at certain times | Mock Date/time |
| External dependencies | Fails intermittently | Mock external services |
| Order dependency | Fails when run in different order | Make tests independent |
// Add retries for known flaky tests (use sparingly!)
test('flaky network test', { retry: 2 }, async () => {
// ...
});
// Log more info on failure
afterEach(function() {
if (this.currentTest?.state === 'failed') {
console.log('Test state:', JSON.stringify(testState, null, 2));
}
});
// Increase timeout if needed
test('slow test', async () => {
// ...
}, 30000); // 30 second timeout
src/
├── users/
│ ├── users.service.ts
│ ├── users.service.spec.ts # Unit tests
│ └── users.controller.ts
│
tests/
├── unit/ # Additional unit tests
├── integration/
│ ├── api/
│ │ └── users.api.spec.ts
│ └── db/
│ └── users.repo.spec.ts
├── e2e/
│ └── user-registration.spec.ts
├── fixtures/
│ └── users.fixture.ts
└── helpers/
├── database.helper.ts
└── auth.helper.ts
// Use descriptive names
describe('UserService')
describe('createUser method')
// "should" format
it('should create user with valid data')
it('should throw when email is duplicate')
it('should hash password before saving')
// Given-When-Then for complex scenarios
it('given authenticated admin, when deleting user, should succeed')
test_quality:
- Tests run independently in any order
- Tests don't depend on external services
- Tests are deterministic (not flaky)
- Tests are fast (<100ms for unit tests)
- Tests have meaningful assertions
- Tests cover happy path AND error cases
- Tests are readable and maintainable
- Tests use realistic data
Before considering testing complete:
skills/kilo-kit/quality/code-review/ - For reviewing test qualityskills/kilo-kit/debugging/verification/ - For verifying fixesskills/kilo-kit/development/backend/ - For testing APIsTesting Strategy Skill v1.0.0 — Test it or regret it
Frequently asked questions
Philosophy: If it's not tested, it's broken. You just don't know it yet.
The source record exposes this install command: npx skills add https://github.com/VoDaiLocz/kilo-kit-mcp --skill "skills/kilo-kit/quality/testing". Inspect the command and pinned source before running it.
Static rules flagged network in the source; the page lists the matching lines and excerpts.
Alternatives
garrytan/gbrain
End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.
alirezarezvani/claude-skills
App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist
dotnet/skills
Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing
vipshop/cache-dit
High-level guide for integrating a new DiT model into cache-dit: Cache (BlockAdapter/ForwardPattern), Context Parallelism, Tensor Parallelism, Text Encoder Parallelism (TE-P), VAE Parallelism (VAE-P), generate CLI, installation, testing workflow, and detailed references. Use when adding support for a new diffusion transformer model in cache-dit.