Files
git.stella-ops.org/docs/testing/mutation-testing-guide.md
master b55d9fa68d
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Add comprehensive security tests for OWASP A03 (Injection) and A10 (SSRF)
- Implemented InjectionTests.cs to cover various injection vulnerabilities including SQL, NoSQL, Command, LDAP, and XPath injections.
- Created SsrfTests.cs to test for Server-Side Request Forgery (SSRF) vulnerabilities, including internal URL access, cloud metadata access, and URL allowlist bypass attempts.
- Introduced MaliciousPayloads.cs to store a collection of malicious payloads for testing various security vulnerabilities.
- Added SecurityAssertions.cs for common security-specific assertion helpers.
- Established SecurityTestBase.cs as a base class for security tests, providing common infrastructure and mocking utilities.
- Configured the test project StellaOps.Security.Tests.csproj with necessary dependencies for testing.
2025-12-16 13:11:57 +02:00

211 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Mutation Testing Guide
This guide documents the integration and usage of Stryker.NET mutation testing in StellaOps.
## Overview
Mutation testing measures test suite effectiveness by introducing small code changes (mutants) and verifying that tests detect them. Unlike line coverage, mutation testing answers: **"Would my tests catch this bug?"**
## Installation
Stryker.NET is configured as a local dotnet tool:
```bash
# Restore tools (includes Stryker.NET)
dotnet tool restore
# Verify installation
dotnet stryker --version
```
## Configuration
### Solution-Level Configuration
Base configuration is at `stryker-config.json` in the solution root. Module-specific configs override these settings.
### Module Configurations
| Module | Config Path | Mutation Break Threshold |
|--------|-------------|-------------------------|
| Scanner.Core | `src/Scanner/__Libraries/StellaOps.Scanner.Core/stryker-config.json` | 60% |
| Policy.Engine | `src/Policy/StellaOps.Policy.Engine/stryker-config.json` | 60% |
| Authority | `src/Authority/StellaOps.Authority/stryker-config.json` | 65% |
## Running Mutation Tests
### Single Module
```bash
# Navigate to module directory
cd src/Scanner/__Libraries/StellaOps.Scanner.Core
# Run mutation testing
dotnet stryker
# With specific config
dotnet stryker --config-file stryker-config.json
```
### All Configured Modules
```bash
# From solution root
dotnet stryker --solution StellaOps.Router.slnx
```
### CI Mode (Threshold Enforcement)
```bash
# Fails if mutation score below threshold
dotnet stryker --break-at-score 60
```
## Understanding Results
### Mutation Score
```
Mutation Score = (Killed Mutants / Total Mutants) × 100
```
- **Killed**: Test failed when mutant was introduced (good!)
- **Survived**: Test passed with mutant present (test gap!)
- **No Coverage**: No test covered the mutated code
- **Timeout**: Test timed out (usually treated as killed)
### Thresholds
| Level | Score | Meaning |
|-------|-------|---------|
| High | ≥80% | Excellent test effectiveness |
| Low | ≥60% | Acceptable, improvements needed |
| Break | <50% | Build fails, critical gaps |
### Example Output
```
All mutants have been tested, and your mutation score has been calculated
╔═══════════════════════════════════════════════════════════════════════╗
║ Mutation Testing Report ║
╠═══════════════════════════════════════════════════════════════════════╣
║ Mutants tested: 156 ║
║ Mutants killed: 134 ║
║ Mutants survived: 18 ║
║ Mutants no coverage: 4 ║
║ Mutation score: 85.90% ║
╚═══════════════════════════════════════════════════════════════════════╝
```
## Common Mutators
| Mutator | Original | Mutant |
|---------|----------|--------|
| Comparison | `>=` | `>` |
| Equality | `==` | `!=` |
| Boolean | `true` | `false` |
| Logical | `&&` | `\|\|` |
| Arithmetic | `+` | `-` |
| NullCoalescing | `??` | ` ` (remove) |
## Fixing Survived Mutants
### 1. Analyze the Report
Open the HTML report in `.stryker/output/<module>/mutation-report.html`.
### 2. Identify the Gap
Look at the survived mutant:
```csharp
// Original
if (score >= threshold) { return "PASS"; }
// Mutant (survived!)
if (score > threshold) { return "PASS"; }
```
### 3. Add Missing Test
```csharp
[Fact]
public void Should_Pass_When_Score_Equals_Threshold()
{
var score = 60;
var threshold = 60;
var result = EvaluateScore(score, threshold);
result.Should().Be("PASS"); // Now kills the >= to > mutant
}
```
## Best Practices
### 1. Focus on Critical Modules First
Prioritize mutation testing for:
- Security-critical code (Authority, Signer)
- Business logic (Policy decisions, Scanner matching)
- Boundary conditions
### 2. Don't Chase 100%
Some mutants are false positives or equivalent mutants. Aim for 80%+ on critical modules.
### 3. Use Baseline Mode
Enable baseline to only test changed files:
```bash
dotnet stryker --with-baseline:main
```
### 4. Exclude Non-Critical Code
Exclude from mutation testing:
- DTOs and models
- Generated code
- Migrations
- UI components
## CI Integration
Mutation testing runs in CI:
```yaml
mutation-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Stryker
run: |
dotnet tool restore
dotnet stryker --break-at-score 60
```
## Troubleshooting
### Slow Execution
- Use `--concurrency` to control parallelism
- Enable `coverage-analysis: perTest` for smarter mutant selection
- Use `--since:main` to only test changed code
### Out of Memory
- Reduce `--concurrency` value
- Exclude large test projects
### Timeout Issues
- Adjust `--timeout` setting
- Some infinite loop mutants may timeout (this is expected)
## References
- [Stryker.NET Documentation](https://stryker-mutator.io/docs/stryker-net/introduction/)
- [Mutation Testing Theory](https://en.wikipedia.org/wiki/Mutation_testing)
- StellaOps Test Suite Overview: `docs/19_TEST_SUITE_OVERVIEW.md`