Skip to content

Conversation

@github-actions
Copy link
Contributor

Summary

Added 30 comprehensive tests for the SpanINumberPrimitives module, covering all major primitive operations used throughout the FsMath library.

⚠️ Important Note: Due to F# inline function limitations, code coverage tools cannot track inline functions. While these tests are functionally complete and thoroughly validate the SpanPrimitives module, the coverage percentage will remain at 0% for this module. This is a known limitation of coverage tooling with F# inline functions, not a deficiency in the tests themselves.

Tests Added

Test Coverage by Function Group

  1. mapInto Functions (6 tests)

    • Basic operations with float/int types
    • Offset and length parameter variations
    • Large arrays to exercise SIMD paths
    • Single element and empty length edge cases
  2. map2Into Functions (6 tests)

    • Binary operations (addition, multiplication)
    • Offset parameter handling
    • SIMD path validation with 100+ element arrays
    • Edge cases (single elements, empty lengths)
  3. mapScalarInto Functions (6 tests)

    • Scalar operations (addition, multiplication, division)
    • Offset-based operations
    • SIMD optimization validation
    • Edge case handling
  4. fold Functions (6 tests)

    • Aggregation operations (sum, product)
    • Offset and length parameter combinations
    • Empty span behavior
    • SIMD path testing
  5. fold2 Functions (6 tests)

    • Dot product calculations
    • Offset parameter variations
    • SIMD optimization with large arrays
    • Edge case validation

Test Strategy

All tests use non-inline wrapper functions in the test module that delegate to the inline SpanINumberPrimitives functions. This approach was chosen to:

  1. Make the test code cleaner and more maintainable
  2. Attempt to provide coverage tracking (though ultimately unsuccessful due to F# inline limitations)
  3. Validate both SIMD-accelerated and scalar fallback code paths

Test Coverage Results

Metric Before After Change
Overall Coverage 32.09% 32.09% +0.00%
SpanPrimitives.fs 0.00% 0.00% +0.00%
Lines Covered (Overall) 657/2047 657/2047 +0 lines
Tests Passing 767 797 +30 tests

Why No Coverage Improvement?

F# inline functions are resolved at compile time and don't exist in the IL as callable methods. Coverage tools instrument IL code, so they cannot track execution of inline functions. Both attempts to work around this failed:

  1. Quotation evaluation (doesn't work with Span/byref types)
  2. Non-inline wrappers (inline functions still optimized away)

Despite 0% reported coverage, all 30 tests pass and thoroughly validate:

  • Correctness of mathematical operations
  • SIMD vs scalar code path behavior
  • Edge case handling
  • Parameter validation

The Challenge with Inline Functions and Coverage

From the previous discussion:

Since F# 8.0 it should be possible to cover inline functions by using quotation evaluation to dynamically invoke them.

While this technique works for some inline functions, it fails for Span-based code because:

  • Span<T> and ReadOnlySpan<T> are byref types
  • Byref types cannot be captured in F# quotations
  • Error: "The byref-typed variable is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions."

Alternatives Considered

  1. Direct wrapper functions (used) - Clean, maintainable, tests work
  2. Quotation evaluation - Doesn't work with Span types
  3. Modify source to make functions non-inline - Would impact performance
  4. Skip testing - Unacceptable, tests are valuable regardless of coverage metrics

Value of This PR

Even without coverage metric improvements, this PR provides:

  1. Functional Validation: 30 passing tests prove SpanPrimitives works correctly
  2. Regression Prevention: Future changes will be caught by these tests
  3. Documentation: Tests serve as usage examples for SpanPrimitives API
  4. SIMD Validation: Tests confirm both SIMD and scalar paths work
  5. Edge Case Coverage: Validates behavior with empty spans, single elements, large arrays

Replicating the Test Coverage Measurements

Commands

# Install dependencies and build
dotnet restore
dotnet build

# Run tests
dotnet test tests/FsMath.Tests/FsMath.Tests.fsproj

# Generate coverage report
dotnet test tests/FsMath.Tests/FsMath.Tests.fsproj \
  --collect:"XPlat Code Coverage" \
  --results-directory ./coverage \
  -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura

# View coverage summary  
python3 << 'EOF'
import xml.etree.ElementTree as ET
tree = ET.parse('./coverage/*/coverage.cobertura.xml')
root = tree.getroot()
line_rate = float(root.get('line-rate', 0))
lines_covered = int(root.get('lines-covered', 0))
lines_valid = int(root.get('lines-valid', 0))
print(f"Coverage: {line_rate * 100:.2f}% ({lines_covered}/{lines_valid} lines)")
EOF

Expected Results

  • ✅ All 797 tests pass (30 new SpanPrimitives tests)
  • ⚠️ Overall coverage: 32.09% (unchanged due to inline function limitation)
  • ⚠️ SpanPrimitives.fs: 0.00% (inline functions not trackable)

Future Improvement Opportunities

Based on the coverage analysis, these modules have good potential for meaningful coverage improvements:

  1. VectorModule.fs - 23.33% coverage, 180 lines

    • Previous work claimed 100% with quotation technique
    • May need to reapply quotation-based tests
  2. Matrix.fs - 42.77% coverage, 720 lines

    • Large module with room for improvement
    • Mix of inline and non-inline functions
  3. MatrixModule.fs - 80.00% coverage, 130 lines

    • Already high coverage, could reach 90%+

Recommendation

While this PR doesn't improve coverage metrics, I recommend:

  1. Merge these tests - They provide real value despite coverage tool limitations
  2. 📝 Document the limitation - Add note to testing guidelines about inline functions
  3. 🎯 Focus future efforts on non-inline code - Target modules like Matrix.fs and VectorModule.fs

The inline function coverage issue is a tooling limitation, not a code quality issue. These tests are valuable and should be preserved.


Bash Commands Executed
# Check git status
git status

# Create branch
git checkout -b daily-test-improver-spanprimitives-coverage-20251012-23100d2d-3d5

# Build and test
dotnet restore
dotnet build tests/FsMath.Tests/FsMath.Tests.fsproj
dotnet test tests/FsMath.Tests/FsMath.Tests.fsproj

# Coverage analysis
dotnet test tests/FsMath.Tests/FsMath.Tests.fsproj \
  --collect:"XPlat Code Coverage" \
  --results-directory ./coverage \
  -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura

# Parse coverage XML
python3 coverage_analysis.py

# Commit changes
git add tests/FsMath.Tests/SpanPrimitivesTests.fs tests/FsMath.Tests/FsMath.Tests.fsproj
git commit -m "Add comprehensive tests for SpanPrimitives module"
Web Searches Performed

None - worked from existing codebase and documentation.

Web Pages Fetched

None - all work based on repository analysis.


🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

AI generated by Daily Test Coverage Improver

- Added 30 tests covering mapInto, map2Into, mapScalarInto, fold, and fold2 functions
- Tests validate both SIMD and scalar code paths
- Tests cover edge cases including single elements, empty lengths, and large arrays
- Tests use non-inline wrappers to attempt coverage tracking

Note: Due to F# inline function limitations, coverage tools cannot track
SpanINumberPrimitives functions. The tests are functionally complete and
validate correctness, but coverage percentage will not reflect this work.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@dsyme dsyme closed this Oct 12, 2025
@dsyme dsyme reopened this Oct 12, 2025
@dsyme dsyme marked this pull request as ready for review October 12, 2025 20:25
@dsyme dsyme merged commit 8678ec0 into main Oct 12, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants