Run mutation testing with Stryker to measure test quality. Identifies weak tests that don't catch code mutations.
Runs mutation testing to identify weak tests by injecting artificial bugs into code and measuring detection rates.
npx claudepluginhub xarlord/devflow-enforcerThis skill inherits all available tools. When active, it can use any tool Claude has access to.
This skill runs mutation testing to measure test suite quality:
Verify that tests actually catch bugs. Use this skill:
1. ANALYZE codebase structure
2. CONFIGURE mutation testing
3. GENERATE mutations
4. RUN tests against each mutation
5. CALCULATE mutation score
6. REPORT surviving mutants
7. SUGGEST test improvements
| Parameter | Type | Description | Required |
|---|---|---|---|
| files | string[] | Files to mutate | No |
| threshold | number | Minimum mutation score | No (default: 80) |
| reporters | string[] | Report formats | No |
| concurrency | number | Parallel processes | No |
// stryker.config.js
module.exports = {
packageManager: 'npm',
reporters: ['html', 'clear-text', 'progress', 'dashboard'],
testRunner: 'jest',
coverageAnalysis: 'perTest',
mutate: ['src/**/*.ts', '!src/**/*.spec.ts'],
thresholds: {
high: 80,
low: 60,
break: 70,
},
jest: {
projectType: 'custom',
config: require('./jest.config.js'),
},
};
# pyproject.toml
[tool.mutmut]
paths_to_mutate = ["src/"]
runner = "pytest -x"
tests_dir = ["tests/"]
<!-- pom.xml -->
<plugin>
<groupId>io.stryker-mutator</groupId>
<artifactId>stryker4s-maven-plugin</artifactId>
<configuration>
<mutate>
<element>src/main/java/**/*.java</element>
</mutate>
<thresholds>
<high>80</high>
<low>60</low>
<break>70</break>
</thresholds>
</configuration>
</plugin>
| Operator | Description | Example |
|---|---|---|
| Arithmetic | Change operators | + → - |
| Conditional | Change conditions | > → >= |
| Equality | Change operators | == → != |
| Boolean | Invert values | true → false |
| String | Change strings | "hello" → "" |
| Array | Change lengths | .length → .length - 1 |
| Object | Remove calls | obj.method() → "" |
# Mutation Testing Report
**Date:** [timestamp]
**Framework:** Stryker
**Duration:** 12m 34s
## Mutation Score
| Metric | Value | Target |
|--------|-------|--------|
| **Mutation Score** | **85%** | 80% ✅ |
| Killed | 170 | - |
| Survived | 20 | - |
| Timeout | 5 | - |
| No Coverage | 5 | - |
| **Total Mutants** | **200** | - |
## File Scores
| File | Score | Killed | Survived |
|------|-------|--------|----------|
| auth.service.ts | 95% | 57 | 3 |
| user.service.ts | 82% | 45 | 10 |
| payment.service.ts | 78% | 39 | 11 |
| email.service.ts | 88% | 35 | 5 |
## Surviving Mutants (Need Tests)
### 1. auth.service.ts:45
**Original:**
```typescript
if (user.isActive) {
return generateToken(user);
}
Mutated:
if (false) { // Changed: user.isActive → false
return generateToken(user);
}
Test Needed: Verify that inactive users cannot get tokens
Suggested Test:
it('should reject inactive users', async () => {
user.isActive = false;
await expect(authService.login(user))
.rejects.toThrow('User is inactive');
});
Original:
const fee = amount * 0.03;
Mutated:
const fee = amount * 0; // Changed: 0.03 → 0
Test Needed: Verify fee calculation
Suggested Test:
it('should calculate correct fee', () => {
const fee = paymentService.calculateFee(100);
expect(fee).toBe(3); // 3% of 100
});
| Reason | Count |
|---|---|
| Equivalent mutation | 5 |
| Not worth testing | 3 |
payment.service.ts fee calculationuser.service.ts
## Example Usage
### Example 1: Run Full Mutation Testing
USER: /mutation-test
SKILL OUTPUT:
Duration: 12m 34s
| Category | Count |
|---|---|
| Killed | 170 |
| Survived | 20 |
| Timeout | 5 |
| No Coverage | 5 |
| Total | 200 |
View Report: reports/mutation/html/index.html
### Example 2: Test Specific File
USER: /mutation-test auth.service.ts
SKILL INPUT: { "files": ["src/services/auth.service.ts"] }
SKILL OUTPUT:
File: auth.service.ts Duration: 2m 15s
| Mutant Type | Killed | Survived |
|---|---|---|
| Conditional | 25 | 2 |
| Equality | 18 | 1 |
| Boolean | 14 | 0 |
| Total | 57 | 3 |
// Original
if (user.isActive) {
// Mutated
if (false) {
Add Test:
it('should reject inactive users', async () => {
const inactiveUser = { ...user, isActive: false };
await expect(service.login(inactiveUser))
.rejects.toThrow('User is inactive');
});
### Example 3: Set Threshold
USER: /mutation-test --threshold 90
SKILL INPUT: { "threshold": 90 }
SKILL OUTPUT:
Threshold: 90% Actual Score: 85%
❌ Build Failed: Mutation score below threshold
Priority fixes needed:
Run npx stryker run to see full report.
## Running Mutation Tests
### JavaScript/TypeScript
```bash
npx stryker run
mutmut run
mvn stryker4s:run
dotnet stryker
# .github/workflows/mutation.yml
name: Mutation Testing
on: [push, pull_request]
jobs:
mutation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx stryker run
env:
STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_TOKEN }}
This skill integrates with:
coverage-analysis: Combined quality metricstest-generation: Generate missing testsSearch, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
This skill should be used when the user asks to "add MCP server", "integrate MCP", "configure MCP in plugin", "use .mcp.json", "set up Model Context Protocol", "connect external service", mentions "${CLAUDE_PLUGIN_ROOT} with MCP", or discusses MCP server types (SSE, stdio, HTTP, WebSocket). Provides comprehensive guidance for integrating Model Context Protocol servers into Claude Code plugins for external tool and service integration.