|
43 | 43 | - name: Test |
44 | 44 | run: dotnet test --configuration Release --no-build |
45 | 45 |
|
| 46 | + # Coverage is collected from Monnify.Tests only (run separately from the line above) - |
| 47 | + # IntegrationTests' skipped tests never execute SUT code, so including that project's |
| 48 | + # report would just dilute the denominator with the same assembly's line count again. |
| 49 | + - name: Test with coverage |
| 50 | + run: dotnet test tests/Monnify.Tests/Monnify.Tests.csproj --configuration Release --no-build --collect:"XPlat Code Coverage" --results-directory ./coverage |
| 51 | + |
| 52 | + # No external service required - just parses the cobertura report coverlet already |
| 53 | + # produces and fails the build below a fixed line-coverage floor. Current baseline is |
| 54 | + # ~95%; 85% leaves headroom for routine work while still catching a real regression. |
| 55 | + - name: Check coverage threshold |
| 56 | + run: | |
| 57 | + python3 - <<'PY' |
| 58 | + import glob, sys, xml.etree.ElementTree as ET |
| 59 | +
|
| 60 | + THRESHOLD = 85.0 |
| 61 | + files = glob.glob("./coverage/**/coverage.cobertura.xml", recursive=True) |
| 62 | + if not files: |
| 63 | + sys.exit("No coverage report found") |
| 64 | +
|
| 65 | + root = ET.parse(files[0]).getroot() |
| 66 | + covered = int(root.get("lines-covered")) |
| 67 | + valid = int(root.get("lines-valid")) |
| 68 | + pct = 100 * covered / valid if valid else 0 |
| 69 | +
|
| 70 | + print(f"Line coverage: {pct:.2f}% ({covered}/{valid})") |
| 71 | + if pct < THRESHOLD: |
| 72 | + sys.exit(f"Coverage {pct:.2f}% is below the {THRESHOLD}% threshold") |
| 73 | + PY |
| 74 | +
|
46 | 75 | # Validates the package actually builds correctly across both target frameworks - this is |
47 | 76 | # NOT a publish step, nothing here touches NuGet.org. No artifact is uploaded either, since |
48 | 77 | # this is only a packaging sanity check, not a release. |
|
0 commit comments