Line Coverage
Tracks how many times each line executed. A line with 0 hits is uncovered.
Measure which lines of your Starlark code execute during tests. Track coverage over time and enforce minimum thresholds in CI.
Enable coverage in your config
Create or update sky.toml:
[test.coverage]enabled = trueoutput = "coverage.lcov"Run your tests
skytest tests/Output:
PASS test_add (0.002s)PASS test_subtract (0.001s)
Results: 2 passed, 0 failedCoverage: 85.0% (17/20 lines)Coverage written to coverage.lcovView the report
Open in your IDE or generate HTML:
genhtml coverage.lcov -o coverage-html/open coverage-html/index.htmlCoverage collection uses the OnExec hook in starlark-go-x to track each line executed during test runs.
┌─────────────────────────┐│ Your Starlark files │└───────────┬─────────────┘ │ ▼┌─────────────────────────┐│ skytest --coverage │ ← OnExec hook records each line└───────────┬─────────────┘ │ ▼┌─────────────────────────┐│ Coverage Report │ ← LCOV, Cobertura, JSON, HTML, Text└─────────────────────────┘Create a module and test:
def add(a, b): return a + b
def divide(a, b): if b == 0: return None # This line may not be covered return a / bload("math.star", "add", "divide")
def test_add(): assert.eq(add(2, 3), 5) assert.eq(add(-1, 1), 0)
def test_divide(): assert.eq(divide(10, 2), 5) # Missing: test for divide by zeroRun with coverage:
$ skytest --coverage math_test.starPASS test_add (0.001s)PASS test_divide (0.001s)
Results: 2 passed, 0 failedCoverage: 83.3% (5/6 lines)The report shows line 6 (return None) was never executed.
Line Coverage
Tracks how many times each line executed. A line with 0 hits is uncovered.
Function Coverage
Tracks which functions were called. Inferred from line hits at function entry points.
| Metric | Status | Description |
|---|---|---|
| Line coverage | ✅ Supported | Which lines executed and how many times |
| Function coverage | ✅ Supported | Which functions were called |
| Branch coverage | 🔜 Planned | Which conditional branches were taken |
[test.coverage]# Enable coverage collectionenabled = true
# Output file path (extension determines format)output = "coverage.lcov"
# Fail if coverage falls below threshold (0 = disabled)fail_under = 80.0For dynamic configuration based on environment:
def configure(): ci = getenv("CI", "") != ""
return { "test": { "coverage": { "enabled": ci, # Only collect in CI "output": "coverage.xml" if ci else "coverage.html", "fail_under": 80 if ci else 0, }, }, }Override config from the command line:
# Enable coverageskytest --coverage tests/
# Specify output fileskytest --coverage --coverage-output=coverage.xml tests/
# Set minimum thresholdskytest --coverage --coverage-fail-under=80 tests/The output format is determined by the file extension:
| Extension | Format | Best For |
|---|---|---|
.txt | Text | Terminal viewing |
.json | JSON | Custom tooling |
.xml | Cobertura | CI systems (Jenkins, GitLab) |
.lcov | LCOV | IDE extensions, genhtml |
.html | HTML | Browser viewing, sharing |
[test.coverage]enabled = true# Change extension to change format:output = "coverage.html" # HTML report# output = "coverage.xml" # Cobertura XML# output = "coverage.lcov" # LCOV tracefilePrevent coverage regressions by setting a minimum threshold:
[test.coverage]enabled = trueoutput = "coverage.lcov"fail_under = 80.0When coverage drops below the threshold:
$ skytest tests/PASS test_add (0.001s)
Results: 1 passed, 0 failedCoverage: 75.0% (15/20 lines)FAIL: Coverage 75.0% is below threshold 80.0%Output Formats
Learn about each format: Text, JSON, Cobertura, LCOV, HTML
CI Integration
Set up coverage in GitHub Actions, GitLab, Jenkins
IDE Setup
View coverage in VS Code, JetBrains IDEs