flow-rs-core 0.1.0-beta.1

Core data structures and algorithms for Flow-RS
Documentation
# Mutation Testing for leptos-flow-core

## Overview

Mutation testing is a powerful technique that helps identify gaps in test coverage by introducing small changes (mutations) to the code and checking if our tests can detect these changes. We've set up `cargo-mutants` to perform mutation testing on our codebase.

## Setup

We've installed and configured `cargo-mutants` with the following configuration in `.cargo/mutants.toml`:

```toml
# Cargo-mutants configuration for leptos-flow-core
# Focused configuration for faster, more targeted mutation testing

# Skip certain function calls that are commonly mutated but not critical
skip_calls = [
    "Default::default",
    "Ok",
    "Err",
    "vec!",
    "String::new",
    "format!",
    "println!",
    "eprintln!",
    "dbg!",
    "assert!",
    "assert_eq!",
    "assert_ne!",
    "panic!",
    "unreachable!",
    "todo!",
    "unimplemented!",
]

# Focus on specific files for initial testing
file = [
    "src/types.rs",      # Core data structures only
]

# Exclude certain patterns
exclude = [
    "**/tests/**",
    "**/benches/**",
    "**/examples/**",
    "**/target/**",
]

# Timeout settings - much shorter for faster iteration
timeout = 15
build_timeout = 10

# Parallel execution
jobs = 1

# Output settings
output = "mutants.out"
colors = "auto"
```

## Key Findings

From our initial mutation testing run, we discovered several important insights:

### 1. Test Coverage Gaps

Cargo-mutants found many mutations that our tests are **not catching** (marked as "MISSED"), including:

- **Arithmetic operations**: Changes to `+`, `-`, `*`, `/` operators in mathematical calculations
- **Comparison operations**: Changes to `<`, `>`, `<=`, `>=`, `==`, `!=` operators
- **Boolean logic**: Changes to `&&`, `||` operators
- **Assignment operations**: Changes to `+=`, `-=`, `*=`, `/=` operators
- **Return value mutations**: Functions returning different values than expected

### 2. Critical Areas Needing Better Test Coverage

Based on the mutations found, these areas need more comprehensive testing:

#### Layout Algorithms (`src/layout.rs`)
- **ForceDirectedLayout**: Mathematical calculations for forces, convergence detection
- **GridLayout**: Position calculations, grid cell assignments
- **HierarchicalLayout**: Tree traversal, position calculations
- **CircularLayout**: Angle calculations, position assignments

#### Spatial Indexing (`src/spatial.rs`)
- **SpatialIndex**: Grid cell calculations, query operations
- **Radius queries**: Distance calculations
- **Nearest neighbor**: Distance comparisons

#### Core Types (`src/types.rs`)
- **Position**: Distance calculations, arithmetic operations
- **Rect**: Intersection logic, bounds calculations
- **Viewport**: Coordinate transformations, bounds checking

### 3. Performance Considerations

Our current test suite is comprehensive but slow, causing timeouts in mutation testing. This suggests we need:

- **Faster unit tests** for core operations
- **Focused integration tests** for complex algorithms
- **Property-based tests** (which we've already implemented) for invariant validation

## Recommended Next Steps

### 1. Add Targeted Unit Tests

Create focused unit tests for the most critical mathematical operations:

```rust
#[cfg(test)]
mod mutation_tests {
    use super::*;

    #[test]
    fn test_position_distance_calculation() {
        let p1 = Position::new(0.0, 0.0);
        let p2 = Position::new(3.0, 4.0);
        assert_eq!(p1.distance_to(p2), 5.0);
    }

    #[test]
    fn test_rect_intersection_logic() {
        let rect1 = Rect::from_pos_size(Position::new(0.0, 0.0), Size::new(10.0, 10.0));
        let rect2 = Rect::from_pos_size(Position::new(5.0, 5.0), Size::new(10.0, 10.0));
        assert!(rect1.intersects(&rect2));
    }
}
```

### 2. Add Edge Case Tests

Focus on boundary conditions and edge cases that mutations might reveal:

```rust
#[test]
fn test_zero_distance() {
    let p1 = Position::new(1.0, 1.0);
    let p2 = Position::new(1.0, 1.0);
    assert_eq!(p1.distance_to(p2), 0.0);
}

#[test]
fn test_negative_coordinates() {
    let p1 = Position::new(-1.0, -1.0);
    let p2 = Position::new(1.0, 1.0);
    assert_eq!(p1.distance_to(p2), 2.0_f64.sqrt() * 2.0);
}
```

### 3. Optimize Test Performance

- Reduce test data sizes for faster execution
- Use `cargo test --release` for performance-critical tests
- Consider using `cargo nextest` for parallel test execution

### 4. Continuous Integration

Set up mutation testing in CI with:
- Limited scope (e.g., only critical functions)
- Longer timeouts
- Parallel execution
- Regular runs (e.g., nightly)

## Usage

### Running Mutation Tests

```bash
# List all possible mutations
cargo mutants --list

# Run mutation tests on specific file
cargo mutants --file "src/types.rs" --timeout 30

# Run mutation tests on specific function
cargo mutants --re "Position::distance_to" --timeout 15

# Run with custom configuration
cargo mutants --config .cargo/mutants.toml
```

### Interpreting Results

- **OK**: Mutation was caught by tests (good!)
- **MISSED**: Mutation was not caught by tests (needs better test coverage)
- **TIMEOUT**: Test execution timed out (needs optimization)
- **UNVIABLE**: Mutation caused compilation failure (expected)

## Conclusion

Mutation testing has revealed significant gaps in our test coverage, particularly around mathematical operations and edge cases. While our property-based tests provide excellent invariant validation, we need more targeted unit tests to catch the specific mutations that cargo-mutants identified.

The next priority should be adding focused unit tests for the most critical mathematical operations, especially in the layout algorithms and spatial indexing components.