diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63e4dbb..536ef43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,7 +118,27 @@ jobs: run: dotnet build backend/ProCoderJi.slnx --configuration Release --no-restore - name: Test backend - run: dotnet test backend/ProCoderJi.slnx --configuration Release --no-build + run: dotnet test backend/ProCoderJi.slnx --configuration Release --no-build --collect:"XPlat Code Coverage" --results-directory "$RUNNER_TEMP/backend-test-results" + + - name: Verify API coverage collection + run: | + python3 - "$RUNNER_TEMP/backend-test-results" <<'PY' + import sys + import xml.etree.ElementTree as ET + from pathlib import Path + + reports = list(Path(sys.argv[1]).rglob("coverage.cobertura.xml")) + covered = any( + int(line.get("hits", "0")) > 0 + for report in reports + for package in ET.parse(report).findall("./packages/package") + if package.get("name") == "ProCoderJi.Api" + for line in package.findall(".//line") + ) + if not covered: + raise SystemExit("Coverage collection did not record executed ProCoderJi.Api lines.") + print("Coverage collection recorded executed ProCoderJi.Api lines.") + PY - name: Verify PostgreSQL migrations # Validates the PostgreSQL schema path; Google sign-in needs separate live checks. diff --git a/backend/tests/ProCoderJi.Api.Tests/ProCoderJi.Api.Tests.csproj b/backend/tests/ProCoderJi.Api.Tests/ProCoderJi.Api.Tests.csproj index 8b6fd34..8550e9c 100644 --- a/backend/tests/ProCoderJi.Api.Tests/ProCoderJi.Api.Tests.csproj +++ b/backend/tests/ProCoderJi.Api.Tests/ProCoderJi.Api.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/backend/tests/ProCoderJi.Api.Tests/packages.lock.json b/backend/tests/ProCoderJi.Api.Tests/packages.lock.json index 0a2f48d..fc79202 100644 --- a/backend/tests/ProCoderJi.Api.Tests/packages.lock.json +++ b/backend/tests/ProCoderJi.Api.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "coverlet.collector": { "type": "Direct", - "requested": "[6.0.4, )", - "resolved": "6.0.4", - "contentHash": "lkhqpF8Pu2Y7IiN7OntbsTtdbpR1syMsm2F3IgX6ootA4ffRqWL5jF7XipHuZQTdVuWG/gVAAcf8mjk8Tz0xPg==" + "requested": "[10.1.0, )", + "resolved": "10.1.0", + "contentHash": "SlYCIHnBYxINSUpR75SiM5JEmnx11pqT+Ac/C/fUqTTA0dLPl9eYzmFXKKuxmQhL3ZdTQl4PBD3YdAxAauaKLQ==" }, "Microsoft.AspNetCore.Mvc.Testing": { "type": "Direct", diff --git a/backend/tests/ProCoderJi.BrowserHost/packages.lock.json b/backend/tests/ProCoderJi.BrowserHost/packages.lock.json index b8e6f4d..201c05c 100644 --- a/backend/tests/ProCoderJi.BrowserHost/packages.lock.json +++ b/backend/tests/ProCoderJi.BrowserHost/packages.lock.json @@ -24,8 +24,8 @@ }, "coverlet.collector": { "type": "Transitive", - "resolved": "6.0.4", - "contentHash": "lkhqpF8Pu2Y7IiN7OntbsTtdbpR1syMsm2F3IgX6ootA4ffRqWL5jF7XipHuZQTdVuWG/gVAAcf8mjk8Tz0xPg==" + "resolved": "10.1.0", + "contentHash": "SlYCIHnBYxINSUpR75SiM5JEmnx11pqT+Ac/C/fUqTTA0dLPl9eYzmFXKKuxmQhL3ZdTQl4PBD3YdAxAauaKLQ==" }, "DnsClient": { "type": "Transitive", @@ -455,7 +455,7 @@ "Microsoft.AspNetCore.Mvc.Testing": "[10.0.15, )", "Microsoft.NET.Test.Sdk": "[18.11.0, )", "ProCoderJi.Api": "[1.0.0, )", - "coverlet.collector": "[6.0.4, )", + "coverlet.collector": "[10.1.0, )", "xunit": "[2.9.3, )", "xunit.runner.visualstudio": "[3.1.5, )" }