Skip to content

(feat) add coverage report to the project #136

@kalwalt

Description

@kalwalt

Code Coverage Setup for WebARKitLib-rs

Introduction

The project has tests that map the whole infrastructure, this is fine but to map clearly and to get a clear idea of how many functions and types we should provide coverage test. We can add it with codecov or any other open source tool.

Here's a complete guide with different options for adding code coverage to the project:

📊 Available Options

Option 1: Tarpaulin ⭐ (Recommended to start)

Pros:

  • 🚀 Fast and easy to install
  • 📱 Generates visual HTML reports
  • ✨ Zero extra configuration
  • 📈 Multi-platform support

Cons:

  • Less accurate with complex code
  • Not ideal for pure WASM

Installation and usage:

# Install
cargo install cargo-tarpaulin

# Generate HTML report
cargo tarpaulin --out Html --output-dir coverage/ --timeout 300

# With exclusions
cargo tarpaulin --exclude-files tests/ --out Html --output-dir coverage/

# Verbose for debugging
cargo tarpaulin -v --out Html --output-dir coverage/

Option 2: cargo-llvm-cov 🎯 (More accurate)

Pros:

  • 🎯 Accurate (uses native LLVM)
  • 📊 Detailed reports
  • 🔧 Ideal for complex projects
  • 📦 Supports WASM and FFI

Cons:

  • Slightly more complex setup
  • Requires specific toolchains

Installation and usage:

# Install
cargo install cargo-llvm-cov

# Generate HTML report
cargo llvm-cov --html

# Lcov report (for CI/CD)
cargo llvm-cov --lcov --output-path coverage.lcov

# Lib only (exclude binaries)
cargo llvm-cov --lib --html

# With threshold
cargo llvm-cov --html --fail-under-lines 80

Option 3: grcov 💪 (Maximum precision)

Pros:

  • 💪 Extremely accurate
  • 🔬 Scientific reports
  • 🎯 Full LLVM support

Cons:

  • More complex setup
  • More verbose

Installation and usage:

# Install
cargo install grcov

# Configure environment
export LLVM_PROFILE_FILE="coverage-%p-%m.profraw"
export RUSTFLAGS="-C instrument-coverage"

# Run tests
cargo test

# Generate report
grcov . -s . --binary-path ./target/debug/ -t html --branch --ignore-not-existing -o ./coverage/

🎯 Quick Comparison

Feature Tarpaulin llvm-cov grcov
Ease of Use ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
Accuracy ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Speed ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
WASM Support ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
CI/CD Integration ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐

Recommendation: Start with Tarpaulin, then migrate to llvm-cov for more accurate coverage.


🛠️ Recommended Complete Setup

1. Test Structure

// src/lib.rs
pub mod marker;
pub mod image_processing;
pub mod tracking;

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_initialization() {
        // basic test
    }
}

// src/marker.rs
pub struct Marker {
    // marker implementation
}

impl Marker {
    pub fn new() -> Self {
        // implementation
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_marker_creation() {
        let marker = Marker::new();
        assert!(!marker.is_empty());
    }

    #[test]
    fn test_marker_detection() {
        // complete test
    }

    #[test]
    #[ignore]  // Slow test, manual execution
    fn test_nft_marker_complex() {
        // complex test with real images
    }
}

2. GitHub Actions Workflow

Create .github/workflows/coverage.yml:

name: Code Coverage

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

jobs:
  coverage:
    runs-on: ubuntu-latest
    name: Generate Coverage Report
    steps:
      - uses: actions/checkout@v4
      
      - name: Install Rust Toolchain
        uses: dtolnay/rust-toolchain@stable
      
      - name: Install Tarpaulin
        run: cargo install cargo-tarpaulin
      
      - name: Generate Coverage
        run: |
          cargo tarpaulin \
            --out Xml \
            --output-dir coverage \
            --timeout 300 \
            --exclude-files tests/ \
            --ignore-panics
      
      - name: Upload to Codecov
        uses: codecov/codecov-action@v3
        with:
          files: ./coverage/cobertura.xml
          flags: rust
          name: coverage-report
          fail_ci_if_error: false
          verbose: true
      
      - name: Archive Coverage Report
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: coverage-report
          path: coverage/

  test:
    runs-on: ubuntu-latest
    name: Run Tests
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - name: Run Tests
        run: cargo test --verbose --lib

3. Local Configuration Files

.tarpaulin.toml:

[coverage]
timeout = 300
ignore-panics = true
ignore-timeouts = true
exclude-files = ["tests/*", "benches/*"]

Cargo.toml (update dev-dependencies):

[dev-dependencies]
# For WASM testing (if applicable)
wasm-bindgen-test = "1.3"

# For property-based testing
proptest = "1.0"

# For benchmarking
criterion = "0.5"

4. Local Script

Create scripts/coverage.sh:

#!/bin/bash
set -e

echo "🧪 Generating Code Coverage Report..."
echo ""

# Clean previous coverage
rm -rf coverage/
mkdir -p coverage/

# Option 1: Using Tarpaulin
echo "Using Tarpaulin for coverage..."
cargo tarpaulin \
    --out Html \
    --output-dir coverage \
    --timeout 300 \
    --exclude-files "tests/*" \
    --ignore-panics \
    --ignore-timeouts \
    --verbose

# Option 2: Using llvm-cov (uncomment to use)
# echo "Using llvm-cov for coverage..."
# cargo llvm-cov --html --output-dir coverage/

echo ""
echo "✅ Coverage report generated!"
echo ""
echo "📊 View report:"
if command -v open &> /dev/null; then
    open coverage/index.html  # macOS
elif command -v xdg-open &> /dev/null; then
    xdg-open coverage/index.html  # Linux
else
    echo "   Open: $(pwd)/coverage/index.html"
fi

Make it executable:

chmod +x scripts/coverage.sh
./scripts/coverage.sh

📈 Setting Up Coverage Goals

.github/workflows/coverage-gate.yml

name: Coverage Gate

on:
  pull_request:
    branches: [ main ]

jobs:
  coverage-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - name: Install cargo-llvm-cov
        run: cargo install cargo-llvm-cov
      
      - name: Check Coverage Threshold
        run: cargo llvm-cov --html --fail-under-lines 75
      
      - name: Comment on PR if coverage fails
        if: failure()
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: '❌ Coverage below 75% threshold. Please add more tests.'
            })

📚 Adding to README.md

## 📊 Code Coverage

[![codecov](https://codecov.io/gh/webarkit/WebARKitLib-rs/branch/main/graph/badge.svg?token=YOUR_TOKEN)](https://codecov.io/gh/webarkit/WebARKitLib-rs)

### Generate Coverage Report Locally

#### With Tarpaulin (Recommended)
```bash
cargo install cargo-tarpaulin
./scripts/coverage.sh
# Open: ./coverage/index.html

With llvm-cov

cargo install cargo-llvm-cov
cargo llvm-cov --html
# Open: ./target/llvm-cov/html/index.html

Coverage Targets

  • Minimum: 75%
  • Desirable: 85%+
  • Critical (Marker Tracking): 95%+

Coverage Exclusions

  • Test files
  • Generated code
  • WASM bindings

---

## 🎯 Implementation Checklist

- [ ] Install coverage tool (tarpaulin or llvm-cov)
- [ ] Add GitHub Actions workflow
- [ ] Test locally: `./scripts/coverage.sh`
- [ ] Configure Codecov integration
- [ ] Add badge to README
- [ ] Set up pull request checks
- [ ] Document coverage targets
- [ ] Exclude non-testable files

---

## 💡 Pro Tips

1. **Exclude FFI/WASM bindings** from coverage:
```rust
#[cfg(not(test))]
#[wasm_bindgen]
pub fn exported_function() { }
  1. Skip expensive tests:
#[test]
#[ignore]
fn expensive_test() { }

// Run only with: cargo test -- --ignored
  1. Use proptest for property-based testing:
#[test]
fn test_property(x in 0i32..100) {
    // Test over range of values
}
  1. Readable CI/CD reports:
# Generate summary
cargo tarpaulin --out Json --output-dir coverage/

🔗 Useful Resources


❓ Questions?

If you have questions about the implementation, feel free to reply! I'm available for:

  • Additional setup
  • Troubleshooting
  • Coverage optimization
  • Advanced CI/CD integration

Metadata

Metadata

No fields configured for Feature.

Projects

Status

In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions