COVERAGE GUIDE - nself-org/cli GitHub Wiki
Complete guide to nself's test coverage system and how to achieve 100% coverage.
- Overview
- Coverage System
- Running Coverage
- Viewing Reports
- Improving Coverage
- Coverage Requirements
- CI/CD Integration
- Troubleshooting
nself aims for 100% test coverage to ensure reliability and quality. Our coverage system tracks:
- Line Coverage: Percentage of code lines executed by tests
- Branch Coverage: Percentage of decision branches taken
- Function Coverage: Percentage of functions called
Current Status: 100% โ
coverage/
โโโ data/ # Raw coverage data from test runs
โ โโโ unit/ # Unit test coverage
โ โโโ integration/ # Integration test coverage
โ โโโ security/ # Security test coverage
โ โโโ e2e/ # End-to-end test coverage
โโโ reports/ # Generated reports
โ โโโ coverage.txt # Text report
โ โโโ coverage.json # JSON data
โ โโโ badge.svg # Coverage badge
โ โโโ html/ # Interactive HTML report
โโโ .coverage-history.json # Historical trend data
- kcov: Bash code coverage collection
- lcov: Coverage data merging
- Custom scripts: Report generation and verification
# Run all tests with coverage tracking
./src/scripts/coverage/collect-coverage.sh
# Generate reports
./src/scripts/coverage/generate-coverage-report.sh
# Verify requirements
./src/scripts/coverage/verify-coverage.sh# One-line coverage check
./src/scripts/coverage/collect-coverage.sh && \
./src/scripts/coverage/generate-coverage-report.sh && \
./src/scripts/coverage/verify-coverage.sh# Unit tests only
COVERAGE_ENABLED=true kcov coverage/data/unit ./src/tests/run-init-tests.sh
# Integration tests only
COVERAGE_ENABLED=true kcov coverage/data/integration ./src/tests/integration/run-all.sh# View in terminal
cat coverage/reports/coverage.txtExample output:
========================================
nself Test Coverage Report
========================================
Overall Coverage: 100.0% (target: 100%)
Line Coverage: 100.0% (5,234 / 5,234 lines)
Branch Coverage: 98.5% (1,234 / 1,253 branches)
Function Coverage: 100.0% (432 / 432 functions)
Progress: [==================================================] 100.0%
Test Statistics:
Total Tests: 700
Passed: 700 (100.0%)
Failed: 0
Skipped: 0
# Open interactive HTML report
open coverage/reports/html/index.htmlFeatures:
- File browser with coverage percentages
- Line-by-line coverage highlighting
- Branch coverage visualization
- Test execution counts
- Uncovered code identification
# View JSON data
cat coverage/reports/coverage.json
# Use with jq
jq '.overall' coverage/reports/coverage.json# Generate report to see uncovered lines
./src/scripts/coverage/generate-coverage-report.sh
# Open HTML report
open coverage/reports/html/index.htmlIn the HTML report:
- Green lines: Covered by tests
- Red lines: Not covered
- Yellow lines: Partially covered (branch coverage)
Example: Adding tests for uncovered function
# File: src/lib/auth/oauth.sh
oauth_validate_token() {
local token="$1"
# Line 1: Covered โ
if [[ -z "$token" ]]; then
return 1
fi
# Line 2: NOT covered โ
if [[ ${#token} -lt 32 ]]; then
return 1
fi
# Line 3: Covered โ
return 0
}Add test:
# File: src/tests/unit/test-oauth.sh
test_oauth_validate_token_short() {
local result
# Test the uncovered branch
oauth_validate_token "short_token"
result=$?
assert_equals 1 "$result" "Should reject short token"
}# Collect coverage
./src/scripts/coverage/collect-coverage.sh
# Verify improvement
./src/scripts/coverage/verify-coverage.sh# Ensure error paths are tested
function process_data() {
local data="$1"
# Test both success and failure
if validate_data "$data"; then
# Success path - needs test โ
return 0
else
# Error path - needs test โ
return 1
fi
}Test both paths:
test_process_data_success() {
process_data "valid"
assert_equals 0 $?
}
test_process_data_failure() {
process_data "invalid"
assert_equals 1 $?
}# Test boundary conditions
test_edge_cases() {
# Empty input
my_function ""
# Very long input
my_function "$(printf 'a%.0s' {1..10000})"
# Special characters
my_function "test@#$%"
}# Test all branches
function calculate_price() {
local quantity="$1"
if [[ $quantity -lt 10 ]]; then
echo "100" # Test with quantity=5 โ
elif [[ $quantity -lt 100 ]]; then
echo "90" # Test with quantity=50 โ
else
echo "80" # Test with quantity=200 โ
fi
}# Set in verify-coverage.sh
REQUIRED_LINE_COVERAGE=100.0 # Enforced โ
REQUIRED_BRANCH_COVERAGE=95.0 # Warning only โ ๏ธ
REQUIRED_FUNCTION_COVERAGE=100.0 # Warning only โ ๏ธ- Line coverage < 100%: CI fails โ
-
Branch coverage < 95%: Warning only
โ ๏ธ -
Function coverage < 100%: Warning only
โ ๏ธ
# Skip coverage verification (NOT recommended)
SKIP_COVERAGE_CHECK=true ./src/scripts/coverage/verify-coverage.shOnly use in emergencies! Coverage requirements exist for a reason.
Coverage runs automatically on:
- Every push to
mainordevelop - Every pull request
Workflow: .github/workflows/coverage.yml
Pull requests automatically get a coverage comment:
## ๐ Coverage Report
**Overall Coverage:** 100.0%
**Target:** 100%
**Gap:** 0.0%
๐ **100% Coverage Achieved!**Badge updates automatically on merge to main:
# Pre-commit hook (optional)
# .git/hooks/pre-commit
./src/scripts/coverage/collect-coverage.sh
./src/scripts/coverage/verify-coverage.sh
if [ $? -ne 0 ]; then
echo "โ Coverage verification failed"
echo "Fix: Add tests to maintain coverage"
exit 1
fiProblem: No coverage data collected
Solution:
# Ensure tools are installed
command -v kcov || sudo apt-get install kcov
# Run collection first
./src/scripts/coverage/collect-coverage.shProblem: Coverage dropped below 100%
Solution:
# View uncovered code
open coverage/reports/html/index.html
# Find red (uncovered) lines
# Write tests for those lines
# Run coverage againProblem: Test suite fails but coverage is collected
Solution:
# Fix failing tests first
./src/tests/run-tests.sh
# Then collect coverage
./src/scripts/coverage/collect-coverage.shProblem: Coverage tool not installed
Solution:
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install kcov
# macOS
brew install kcov
# Or use manual instrumentation (slower)
COVERAGE_ENABLED=true bash test-file.shProblem: PR reduces coverage
Solution:
# Show coverage diff
./src/scripts/coverage/coverage-diff.sh
# Identify new uncovered code
# Add tests for new code
# Ensure new code is covered# 1. Write failing test
test_new_feature() {
new_feature
assert_equals 0 $?
}
# 2. Implement feature
new_feature() {
# Implementation
return 0
}
# 3. Verify test passes
# Coverage automatically at 100%# Bad: Only tests happy path
test_process() {
process_data "valid"
assert_equals 0 $?
}
# Good: Tests all paths
test_process_valid() {
process_data "valid"
assert_equals 0 $?
}
test_process_invalid() {
process_data "invalid"
assert_equals 1 $?
}
test_process_empty() {
process_data ""
assert_equals 1 $?
}# After implementing feature
./src/scripts/coverage/collect-coverage.sh
./src/scripts/coverage/generate-coverage-report.sh
# Review HTML report
# Add tests for any red lines# Before committing
./src/scripts/coverage/verify-coverage.sh
# Only commit if verification passesView coverage trends:
# Show trend chart
./src/scripts/coverage/track-coverage-history.sh show
# Generate trend report
./src/scripts/coverage/track-coverage-history.sh reportExample output:
Coverage Trend:
Commit Date Coverage Change
--------------------------------------------------
af3ad41 2026-01-31 100.0% +35.0%
5184aa5 2026-01-30 65.0% +5.0%
b0af0e0 2026-01-29 60.0% +0.0%
-
Coverage Scripts:
/src/scripts/coverage/ -
Test Suites:
/src/tests/ -
CI Workflow:
/.github/workflows/coverage.yml -
Coverage Data:
/coverage/
Coverage issues? Check:
-
HTML Report:
coverage/reports/html/index.html -
Text Report:
coverage/reports/coverage.txt - CI Logs: GitHub Actions workflow logs
- This Guide: You're reading it!
Goal: 100% test coverage
How to achieve:
- Run:
./src/scripts/coverage/collect-coverage.sh - Review:
open coverage/reports/html/index.html - Write tests for red lines
- Verify:
./src/scripts/coverage/verify-coverage.sh - Repeat until 100%
Maintain:
- CI enforces coverage
- Pre-commit hooks (optional)
- Regular trend review
๐ฏ Target: 100% โ Status: ACHIEVED! ๐